ruby-audio 0.2.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +7 -6
- data/Rakefile +14 -21
- data/ext/extconf.rb +12 -0
- data/ext/ra_buffer.c +277 -0
- data/ext/ra_buffer.h +39 -0
- data/ext/ra_sound.c +274 -0
- data/ext/ra_sound.h +37 -0
- data/ext/ra_soundinfo.c +165 -0
- data/ext/ra_soundinfo.h +25 -0
- data/ext/rubyaudio_ext.c +91 -0
- data/lib/ruby-audio.rb +4 -0
- data/lib/ruby-audio/buffer.rb +17 -0
- data/lib/ruby-audio/sound.rb +85 -0
- data/lib/ruby-audio/sound_info.rb +40 -0
- data/spec/buffer_spec.rb +50 -0
- data/spec/data/what.mp3 +0 -0
- data/{test → spec/data}/what.wav +0 -0
- data/{test → spec/data}/what2.wav +0 -0
- data/spec/sound_info_spec.rb +39 -0
- data/spec/sound_spec.rb +147 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +12 -0
- metadata +37 -31
- data/TODO +0 -5
- data/examples/load_samples.rb +0 -27
- data/examples/t.rb +0 -10
- data/ext/sndfile/extconf.rb +0 -31
- data/ext/sndfile/sndfile.i +0 -90
- data/lib/audio.rb +0 -134
- data/lib/audio/sndfile.rb +0 -156
- data/test/test_audio.rb +0 -82
- data/test/test_sndfile.rb +0 -191
data/ext/ra_sound.h
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#ifndef RA_SOUND_H
|
2
|
+
#define RA_SOUND_H
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <sndfile.h>
|
6
|
+
#include "ra_soundinfo.h"
|
7
|
+
#include "ra_buffer.h"
|
8
|
+
|
9
|
+
typedef struct {
|
10
|
+
SNDFILE *snd;
|
11
|
+
VALUE info;
|
12
|
+
int mode;
|
13
|
+
int closed;
|
14
|
+
} RA_SOUND;
|
15
|
+
|
16
|
+
void Init_ra_sound();
|
17
|
+
|
18
|
+
/*** Initialization and Memory Manangement ***/
|
19
|
+
static VALUE ra_sound_allocate(VALUE klass);
|
20
|
+
static void ra_sound_mark(RA_SOUND *snd);
|
21
|
+
static void ra_sound_free(RA_SOUND *snd);
|
22
|
+
|
23
|
+
/*** Singleton Methods ***/
|
24
|
+
static VALUE ra_sound_s_open(int argc, VALUE *argv, VALUE klass);
|
25
|
+
|
26
|
+
/*** Instance Methods ***/
|
27
|
+
static VALUE ra_sound_init(VALUE self, VALUE path, VALUE mode, VALUE info);
|
28
|
+
static VALUE ra_sound_info(VALUE self);
|
29
|
+
static VALUE ra_sound_seek(VALUE self, VALUE frames, VALUE whence);
|
30
|
+
static VALUE ra_sound_read(VALUE self, VALUE buf, VALUE frames);
|
31
|
+
static VALUE ra_sound_write(VALUE self, VALUE buf);
|
32
|
+
static VALUE ra_sound_addbuf(VALUE self, VALUE buf);
|
33
|
+
static VALUE ra_sound_close(VALUE self);
|
34
|
+
static VALUE ra_sound_close_safe(VALUE self);
|
35
|
+
static VALUE ra_sound_closed(VALUE self);
|
36
|
+
|
37
|
+
#endif // #ifndef RA_SOUND_H
|
data/ext/ra_soundinfo.c
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
#include "ra_soundinfo.h"
|
2
|
+
|
3
|
+
extern VALUE eRubyAudioError;
|
4
|
+
|
5
|
+
/*
|
6
|
+
* Class <code>CSoundInfo</code> is a very light wrapper around the
|
7
|
+
* <code>SF_INFO</code> struct exposed by libsndfile. It provides information
|
8
|
+
* about open sound files like format, length, samplerate, channels, and other
|
9
|
+
* things. In addition it can be used to specify the format of new sound files.
|
10
|
+
*/
|
11
|
+
void Init_ra_soundinfo() {
|
12
|
+
VALUE mRubyAudio = rb_define_module("RubyAudio");
|
13
|
+
VALUE cRASoundInfo = rb_define_class_under(mRubyAudio, "CSoundInfo", rb_cObject);
|
14
|
+
rb_define_alloc_func(cRASoundInfo, ra_soundinfo_allocate);
|
15
|
+
rb_define_method(cRASoundInfo, "valid?", ra_soundinfo_valid, 0);
|
16
|
+
rb_define_method(cRASoundInfo, "frames", ra_soundinfo_frames, 0);
|
17
|
+
rb_define_method(cRASoundInfo, "samplerate", ra_soundinfo_samplerate, 0);
|
18
|
+
rb_define_method(cRASoundInfo, "samplerate=", ra_soundinfo_samplerate_set, 1);
|
19
|
+
rb_define_method(cRASoundInfo, "channels", ra_soundinfo_channels, 0);
|
20
|
+
rb_define_method(cRASoundInfo, "channels=", ra_soundinfo_channels_set, 1);
|
21
|
+
rb_define_method(cRASoundInfo, "format", ra_soundinfo_format, 0);
|
22
|
+
rb_define_method(cRASoundInfo, "format=", ra_soundinfo_format_set, 1);
|
23
|
+
rb_define_method(cRASoundInfo, "sections", ra_soundinfo_sections, 0);
|
24
|
+
rb_define_method(cRASoundInfo, "seekable", ra_soundinfo_seekable, 0);
|
25
|
+
}
|
26
|
+
|
27
|
+
static VALUE ra_soundinfo_allocate(VALUE klass) {
|
28
|
+
SF_INFO *info = ALLOC(SF_INFO);
|
29
|
+
memset(info, 0, sizeof(SF_INFO));
|
30
|
+
VALUE self = Data_Wrap_Struct(klass, NULL, ra_soundinfo_free, info);
|
31
|
+
return self;
|
32
|
+
}
|
33
|
+
|
34
|
+
static void ra_soundinfo_free(SF_INFO *info) {
|
35
|
+
xfree(info);
|
36
|
+
}
|
37
|
+
|
38
|
+
/*
|
39
|
+
* call-seq:
|
40
|
+
* info.valid? => true or false
|
41
|
+
*
|
42
|
+
* Calls <code>sf_format_check</code> on the underlying <code>SF_INFO</code>
|
43
|
+
* struct and returns true or false based on validity. Used when creating a new
|
44
|
+
* sound file to check that the format has enough information to properly create
|
45
|
+
* a new sound.
|
46
|
+
*/
|
47
|
+
static VALUE ra_soundinfo_valid(VALUE self) {
|
48
|
+
SF_INFO *info;
|
49
|
+
Data_Get_Struct(self, SF_INFO, info);
|
50
|
+
return sf_format_check(info) ? Qtrue : Qfalse;
|
51
|
+
}
|
52
|
+
|
53
|
+
/*
|
54
|
+
* call-seq:
|
55
|
+
* info.frames => integer
|
56
|
+
*
|
57
|
+
* Returns the number of frames in the associated sound file.
|
58
|
+
*/
|
59
|
+
static VALUE ra_soundinfo_frames(VALUE self) {
|
60
|
+
SF_INFO *info;
|
61
|
+
Data_Get_Struct(self, SF_INFO, info);
|
62
|
+
return OFFT2NUM(info->frames);
|
63
|
+
}
|
64
|
+
|
65
|
+
/*
|
66
|
+
* call-seq:
|
67
|
+
* info.samplerate => integer
|
68
|
+
*
|
69
|
+
* Returns the samplerate of the associated sound file.
|
70
|
+
*/
|
71
|
+
static VALUE ra_soundinfo_samplerate(VALUE self) {
|
72
|
+
SF_INFO *info;
|
73
|
+
Data_Get_Struct(self, SF_INFO, info);
|
74
|
+
return INT2FIX(info->samplerate);
|
75
|
+
}
|
76
|
+
|
77
|
+
/*
|
78
|
+
* call-seq:
|
79
|
+
* info.samplerate = integer => integer
|
80
|
+
*
|
81
|
+
* Set the samplerate for a new sound created with the given info object.
|
82
|
+
*/
|
83
|
+
static VALUE ra_soundinfo_samplerate_set(VALUE self, VALUE new_samplerate) {
|
84
|
+
SF_INFO *info;
|
85
|
+
Data_Get_Struct(self, SF_INFO, info);
|
86
|
+
info->samplerate = FIX2INT(new_samplerate);
|
87
|
+
return new_samplerate;
|
88
|
+
}
|
89
|
+
|
90
|
+
/*
|
91
|
+
* call-seq:
|
92
|
+
* info.channels => integer
|
93
|
+
*
|
94
|
+
* Returns the number of channels in the associated sound file.
|
95
|
+
*/
|
96
|
+
static VALUE ra_soundinfo_channels(VALUE self) {
|
97
|
+
SF_INFO *info;
|
98
|
+
Data_Get_Struct(self, SF_INFO, info);
|
99
|
+
return INT2FIX(info->channels);
|
100
|
+
}
|
101
|
+
|
102
|
+
/*
|
103
|
+
* call-seq:
|
104
|
+
* info.channels = integer => integer
|
105
|
+
*
|
106
|
+
* Set the number of channels for a new sound created with the given info object.
|
107
|
+
*/
|
108
|
+
static VALUE ra_soundinfo_channels_set(VALUE self, VALUE new_channels) {
|
109
|
+
SF_INFO *info;
|
110
|
+
Data_Get_Struct(self, SF_INFO, info);
|
111
|
+
info->channels = FIX2INT(new_channels);
|
112
|
+
return new_channels;
|
113
|
+
}
|
114
|
+
|
115
|
+
/*
|
116
|
+
* call-seq:
|
117
|
+
* info.format => integer
|
118
|
+
*
|
119
|
+
* Returns the format as a combination of binary flags of the associated sound file.
|
120
|
+
*/
|
121
|
+
static VALUE ra_soundinfo_format(VALUE self) {
|
122
|
+
SF_INFO *info;
|
123
|
+
Data_Get_Struct(self, SF_INFO, info);
|
124
|
+
return INT2FIX(info->format);
|
125
|
+
}
|
126
|
+
|
127
|
+
/*
|
128
|
+
* call-seq:
|
129
|
+
* info.format = integer => integer
|
130
|
+
*
|
131
|
+
* Set the format for a new sound created with the given info object.
|
132
|
+
*
|
133
|
+
* info = RubyAudio::CSoundInfo.new
|
134
|
+
* info.format = RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
|
135
|
+
*/
|
136
|
+
static VALUE ra_soundinfo_format_set(VALUE self, VALUE new_format) {
|
137
|
+
SF_INFO *info;
|
138
|
+
Data_Get_Struct(self, SF_INFO, info);
|
139
|
+
info->format = FIX2INT(new_format);
|
140
|
+
return new_format;
|
141
|
+
}
|
142
|
+
|
143
|
+
/*
|
144
|
+
* call-seq:
|
145
|
+
* info.sections => integer
|
146
|
+
*
|
147
|
+
* Returns the number of sections in the associated sound file.
|
148
|
+
*/
|
149
|
+
static VALUE ra_soundinfo_sections(VALUE self) {
|
150
|
+
SF_INFO *info;
|
151
|
+
Data_Get_Struct(self, SF_INFO, info);
|
152
|
+
return INT2FIX(info->sections);
|
153
|
+
}
|
154
|
+
|
155
|
+
/*
|
156
|
+
* call-seq:
|
157
|
+
* info.seekable => true or false
|
158
|
+
*
|
159
|
+
* Whether seeking is supported for the associated sound file.
|
160
|
+
*/
|
161
|
+
static VALUE ra_soundinfo_seekable(VALUE self) {
|
162
|
+
SF_INFO *info;
|
163
|
+
Data_Get_Struct(self, SF_INFO, info);
|
164
|
+
return info->seekable ? Qtrue : Qfalse;
|
165
|
+
}
|
data/ext/ra_soundinfo.h
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#ifndef RA_SOUNDINFO_H
|
2
|
+
#define RA_SOUNDINFO_H
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <sndfile.h>
|
6
|
+
|
7
|
+
void Init_ra_soundinfo();
|
8
|
+
|
9
|
+
/*** Initialization and Memory Manangement ***/
|
10
|
+
static VALUE ra_soundinfo_allocate(VALUE klass);
|
11
|
+
static void ra_soundinfo_free(SF_INFO *info);
|
12
|
+
|
13
|
+
/*** Instance Methods ***/
|
14
|
+
static VALUE ra_soundinfo_valid(VALUE self);
|
15
|
+
static VALUE ra_soundinfo_frames(VALUE self);
|
16
|
+
static VALUE ra_soundinfo_samplerate(VALUE self);
|
17
|
+
static VALUE ra_soundinfo_samplerate_set(VALUE self, VALUE new_samplerate);
|
18
|
+
static VALUE ra_soundinfo_channels(VALUE self);
|
19
|
+
static VALUE ra_soundinfo_channels_set(VALUE self, VALUE new_channels);
|
20
|
+
static VALUE ra_soundinfo_format(VALUE self);
|
21
|
+
static VALUE ra_soundinfo_format_set(VALUE self, VALUE new_format);
|
22
|
+
static VALUE ra_soundinfo_sections(VALUE self);
|
23
|
+
static VALUE ra_soundinfo_seekable(VALUE self);
|
24
|
+
|
25
|
+
#endif // #ifndef RA_SOUNDINFO_H
|
data/ext/rubyaudio_ext.c
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <sndfile.h>
|
3
|
+
|
4
|
+
void Init_ra_buffer();
|
5
|
+
void Init_ra_soundinfo();
|
6
|
+
void Init_ra_sound();
|
7
|
+
|
8
|
+
VALUE eRubyAudioError;
|
9
|
+
|
10
|
+
/*
|
11
|
+
* Document-module: RubyAudio
|
12
|
+
*/
|
13
|
+
/*
|
14
|
+
* Document-class: RubyAudio::Error
|
15
|
+
*
|
16
|
+
* Error class for RubyAudio
|
17
|
+
*/
|
18
|
+
void Init_rubyaudio_ext() {
|
19
|
+
// Create RubyAudio module and other setup
|
20
|
+
VALUE mRubyAudio = rb_define_module("RubyAudio");
|
21
|
+
eRubyAudioError = rb_define_class_under(mRubyAudio, "Error", rb_eStandardError);
|
22
|
+
|
23
|
+
// Set up classes
|
24
|
+
Init_ra_buffer();
|
25
|
+
Init_ra_soundinfo();
|
26
|
+
Init_ra_sound();
|
27
|
+
|
28
|
+
// Export libsndfile constants
|
29
|
+
// Major formats
|
30
|
+
rb_define_const(mRubyAudio, "FORMAT_WAV", INT2FIX(SF_FORMAT_WAV));
|
31
|
+
rb_define_const(mRubyAudio, "FORMAT_AIFF", INT2FIX(SF_FORMAT_AIFF));
|
32
|
+
rb_define_const(mRubyAudio, "FORMAT_AU", INT2FIX(SF_FORMAT_AU));
|
33
|
+
rb_define_const(mRubyAudio, "FORMAT_RAW", INT2FIX(SF_FORMAT_RAW));
|
34
|
+
rb_define_const(mRubyAudio, "FORMAT_PAF", INT2FIX(SF_FORMAT_PAF));
|
35
|
+
rb_define_const(mRubyAudio, "FORMAT_SVX", INT2FIX(SF_FORMAT_SVX));
|
36
|
+
rb_define_const(mRubyAudio, "FORMAT_NIST", INT2FIX(SF_FORMAT_NIST));
|
37
|
+
rb_define_const(mRubyAudio, "FORMAT_VOC", INT2FIX(SF_FORMAT_VOC));
|
38
|
+
rb_define_const(mRubyAudio, "FORMAT_IRCAM", INT2FIX(SF_FORMAT_IRCAM));
|
39
|
+
rb_define_const(mRubyAudio, "FORMAT_W64", INT2FIX(SF_FORMAT_W64));
|
40
|
+
rb_define_const(mRubyAudio, "FORMAT_MAT4", INT2FIX(SF_FORMAT_MAT4));
|
41
|
+
rb_define_const(mRubyAudio, "FORMAT_MAT5", INT2FIX(SF_FORMAT_MAT5));
|
42
|
+
rb_define_const(mRubyAudio, "FORMAT_PVF", INT2FIX(SF_FORMAT_PVF));
|
43
|
+
rb_define_const(mRubyAudio, "FORMAT_XI", INT2FIX(SF_FORMAT_XI));
|
44
|
+
rb_define_const(mRubyAudio, "FORMAT_HTK", INT2FIX(SF_FORMAT_HTK));
|
45
|
+
rb_define_const(mRubyAudio, "FORMAT_SDS", INT2FIX(SF_FORMAT_SDS));
|
46
|
+
rb_define_const(mRubyAudio, "FORMAT_AVR", INT2FIX(SF_FORMAT_AVR));
|
47
|
+
rb_define_const(mRubyAudio, "FORMAT_WAVEX", INT2FIX(SF_FORMAT_WAVEX));
|
48
|
+
rb_define_const(mRubyAudio, "FORMAT_SD2", INT2FIX(SF_FORMAT_SD2));
|
49
|
+
rb_define_const(mRubyAudio, "FORMAT_FLAC", INT2FIX(SF_FORMAT_FLAC));
|
50
|
+
rb_define_const(mRubyAudio, "FORMAT_CAF", INT2FIX(SF_FORMAT_CAF));
|
51
|
+
rb_define_const(mRubyAudio, "FORMAT_WVE", INT2FIX(SF_FORMAT_WVE));
|
52
|
+
rb_define_const(mRubyAudio, "FORMAT_OGG", INT2FIX(SF_FORMAT_OGG));
|
53
|
+
rb_define_const(mRubyAudio, "FORMAT_MPC2K", INT2FIX(SF_FORMAT_MPC2K));
|
54
|
+
rb_define_const(mRubyAudio, "FORMAT_RF64", INT2FIX(SF_FORMAT_RF64));
|
55
|
+
|
56
|
+
// Subtypes from here on
|
57
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_S8", INT2FIX(SF_FORMAT_PCM_S8));
|
58
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_16", INT2FIX(SF_FORMAT_PCM_16));
|
59
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_24", INT2FIX(SF_FORMAT_PCM_24));
|
60
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_32", INT2FIX(SF_FORMAT_PCM_32));
|
61
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_U8", INT2FIX(SF_FORMAT_PCM_U8));
|
62
|
+
rb_define_const(mRubyAudio, "FORMAT_FLOAT", INT2FIX(SF_FORMAT_FLOAT));
|
63
|
+
rb_define_const(mRubyAudio, "FORMAT_DOUBLE", INT2FIX(SF_FORMAT_DOUBLE));
|
64
|
+
rb_define_const(mRubyAudio, "FORMAT_ULAW", INT2FIX(SF_FORMAT_ULAW));
|
65
|
+
rb_define_const(mRubyAudio, "FORMAT_ALAW", INT2FIX(SF_FORMAT_ALAW));
|
66
|
+
rb_define_const(mRubyAudio, "FORMAT_IMA_ADPCM", INT2FIX(SF_FORMAT_IMA_ADPCM));
|
67
|
+
rb_define_const(mRubyAudio, "FORMAT_MS_ADPCM", INT2FIX(SF_FORMAT_MS_ADPCM));
|
68
|
+
rb_define_const(mRubyAudio, "FORMAT_GSM610", INT2FIX(SF_FORMAT_GSM610));
|
69
|
+
rb_define_const(mRubyAudio, "FORMAT_VOX_ADPCM", INT2FIX(SF_FORMAT_VOX_ADPCM));
|
70
|
+
rb_define_const(mRubyAudio, "FORMAT_G721_32", INT2FIX(SF_FORMAT_G721_32));
|
71
|
+
rb_define_const(mRubyAudio, "FORMAT_G723_24", INT2FIX(SF_FORMAT_G723_24));
|
72
|
+
rb_define_const(mRubyAudio, "FORMAT_G723_40", INT2FIX(SF_FORMAT_G723_40));
|
73
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_12", INT2FIX(SF_FORMAT_DWVW_12));
|
74
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_16", INT2FIX(SF_FORMAT_DWVW_16));
|
75
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_24", INT2FIX(SF_FORMAT_DWVW_24));
|
76
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_N", INT2FIX(SF_FORMAT_DWVW_N));
|
77
|
+
rb_define_const(mRubyAudio, "FORMAT_DPCM_8", INT2FIX(SF_FORMAT_DPCM_8));
|
78
|
+
rb_define_const(mRubyAudio, "FORMAT_DPCM_16", INT2FIX(SF_FORMAT_DPCM_16));
|
79
|
+
rb_define_const(mRubyAudio, "FORMAT_VORBIS", INT2FIX(SF_FORMAT_VORBIS));
|
80
|
+
|
81
|
+
// Endian-ness options
|
82
|
+
rb_define_const(mRubyAudio, "ENDIAN_FILE", INT2FIX(SF_ENDIAN_FILE));
|
83
|
+
rb_define_const(mRubyAudio, "ENDIAN_LITTLE", INT2FIX(SF_ENDIAN_LITTLE));
|
84
|
+
rb_define_const(mRubyAudio, "ENDIAN_BIG", INT2FIX(SF_ENDIAN_BIG));
|
85
|
+
rb_define_const(mRubyAudio, "ENDIAN_CPU", INT2FIX(SF_ENDIAN_CPU));
|
86
|
+
|
87
|
+
// Format masks
|
88
|
+
rb_define_const(mRubyAudio, "FORMAT_SUBMASK", INT2FIX(SF_FORMAT_SUBMASK));
|
89
|
+
rb_define_const(mRubyAudio, "FORMAT_TYPEMASK", INT2FIX(SF_FORMAT_TYPEMASK));
|
90
|
+
rb_define_const(mRubyAudio, "FORMAT_ENDMASK", INT2FIX(SF_FORMAT_ENDMASK));
|
91
|
+
}
|
data/lib/ruby-audio.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module RubyAudio
|
2
|
+
# The <code>Buffer</code> class contains sound data read out of the sound. It
|
3
|
+
# can store a fixed maximum number of multi-channel audio frames of a specifi
|
4
|
+
# data type. Valid types are <code>short</code>, <code>int</code>,
|
5
|
+
# <code>float</code>, and <code>double</code>. The channel count must match up
|
6
|
+
# to the channel count of the sounds being read and written to. Trying to read
|
7
|
+
# into a buffer with the wrong number of channels will result in an error.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
# buf = RubyAudio::Buffer.float(1000)
|
11
|
+
# buf = RubyAudio::Buffer.new("float", 1000, 1)
|
12
|
+
class Buffer < CBuffer
|
13
|
+
[:short, :int, :float, :double].each do |type|
|
14
|
+
eval "def self.#{type}(frames, channels=1); self.new(:#{type}, frames, channels); end"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module RubyAudio
|
2
|
+
# Class <code>Sound</code> wraps libsndfile to provide simple reading and
|
3
|
+
# writing for a wide variety of file formats
|
4
|
+
#
|
5
|
+
# Reading Example:
|
6
|
+
# RubyAudio::Sound.open('sound.wav') do |snd|
|
7
|
+
# buf = snd.read(:float, 100)
|
8
|
+
# puts buf.real_size #=> 100
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# Writing Example:
|
12
|
+
# buf = RubyAudio::Buffer.float(1000)
|
13
|
+
# out = nil
|
14
|
+
# ['snd1.wav', 'snd2.wav', 'snd3.wav'].each do |file|
|
15
|
+
# RubyAudio::Sound.open(file) do |snd|
|
16
|
+
# out = RubyAudio::Sound.open('out.wav', 'w', snd.info.clone) if out.nil?
|
17
|
+
#
|
18
|
+
# while snd.read(buf) != 0
|
19
|
+
# out.write(buf)
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# out.close if out
|
24
|
+
class Sound < CSound
|
25
|
+
# Creates a new <code>Sound</code> object for the audio file at the given path.
|
26
|
+
# Mode defaults to <code>"r"</code>, but valid modes are <code>"r"</code>,
|
27
|
+
# <code>"w"</code>, and <code>"rw"</code>.
|
28
|
+
#
|
29
|
+
# When creating a new sound, a valid <code>SoundInfo</code> object must be
|
30
|
+
# passed in, as libsndfile uses it to determine the output format.
|
31
|
+
# info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
|
32
|
+
# snd = RubyAudio::Sound.new "new.wav", 'r', info
|
33
|
+
def initialize(path, mode='r', info=nil)
|
34
|
+
info ||= SoundInfo.new
|
35
|
+
super(path, mode, info)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Seeks to a given offset <i>anInteger</i> in the sound according to the value
|
39
|
+
# of <i>whence</i>:
|
40
|
+
#
|
41
|
+
# IO::SEEK_CUR | Seeks to _frames_ plus current position
|
42
|
+
# --------------+----------------------------------------------------
|
43
|
+
# IO::SEEK_END | Seeks to _frames_ plus end of stream (you probably
|
44
|
+
# | want a negative value for _frames_)
|
45
|
+
# --------------+----------------------------------------------------
|
46
|
+
# IO::SEEK_SET | Seeks to the absolute location given by _frames_
|
47
|
+
def seek(frames, whence=IO::SEEK_SET)
|
48
|
+
super(frames, whence)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Reads a given number of frames from the sound into a buffer
|
52
|
+
#
|
53
|
+
# When given a buffer as the first argument, it reads data into that buffer
|
54
|
+
# reading an optional number of frames as the second argument. It returns
|
55
|
+
# the number of frames read.
|
56
|
+
#
|
57
|
+
# Example:
|
58
|
+
# buf = RubyAudio::Buffer.float(1000)
|
59
|
+
# snd.read(buf) #=> 1000
|
60
|
+
# snd.read(buf, 50) #=> 50
|
61
|
+
#
|
62
|
+
# When given a string or symbol as the first argument, it interprets this as
|
63
|
+
# the data type and creates a new buffer of the given size to read the data
|
64
|
+
# into. The buffer is correctly initialized with the proper number of channels
|
65
|
+
# to hold data from that sound.
|
66
|
+
#
|
67
|
+
# Example:
|
68
|
+
# buf = snd.read("int", 1000)
|
69
|
+
def read(*args)
|
70
|
+
case args[0]
|
71
|
+
when Buffer
|
72
|
+
buf = args[0]
|
73
|
+
size = args[1] || buf.size
|
74
|
+
return super(buf, size)
|
75
|
+
when Symbol, String
|
76
|
+
type = args[0]
|
77
|
+
buf = Buffer.new(type, args[1], info.channels)
|
78
|
+
super(buf, buf.size)
|
79
|
+
return buf
|
80
|
+
else
|
81
|
+
raise ArgumentError, "invalid arguments"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RubyAudio
|
2
|
+
# Class <code>SoundInfo</code> provides information about open sound files'
|
3
|
+
# format, length, samplerate, channels, and other things.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# snd = RubyAudio::Sound.open("snd.wav")
|
7
|
+
# puts snd.info.channels #=> 2
|
8
|
+
# puts snd.info.samplerate #=> 48000
|
9
|
+
# snd.close
|
10
|
+
#
|
11
|
+
# In addition it can be used to specify the format of new sound files:
|
12
|
+
#
|
13
|
+
# info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
|
14
|
+
# snd = RubyAudio::Sound.open("new.wav", 'w', info)
|
15
|
+
class SoundInfo < CSoundInfo
|
16
|
+
# Creates a new SoundInfo object and populates it using the given data
|
17
|
+
#
|
18
|
+
# Example:
|
19
|
+
# info = RubyAudio::SoundInfo.new :channels => 1, :samplerate => 48000, :format => RubyAudio::FORMAT_WAV|RubyAudio::FORMAT_PCM_16
|
20
|
+
def initialize options={}
|
21
|
+
# Populate from options if given
|
22
|
+
unless options.empty?
|
23
|
+
options.each {|key,value| send("#{key}=", value)}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns a new <code>SoundInfo</code> object that is has the same channel
|
28
|
+
# count, sample rate, and format. This is useful in creating a new sound with
|
29
|
+
# the same format as an already existing sound.
|
30
|
+
#
|
31
|
+
# Example:
|
32
|
+
# snd1 = RubyAudio::Sound.open("snd.wav")
|
33
|
+
# snd2 = RubyAudio::Sound.open("snd2.wav", 'w', snd1.info.clone)
|
34
|
+
def clone
|
35
|
+
SoundInfo.new(:channels => channels, :samplerate => samplerate, :format => format)
|
36
|
+
end
|
37
|
+
|
38
|
+
alias_method :seekable?, :seekable
|
39
|
+
end
|
40
|
+
end
|