ruby-audio 1.5.0-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +340 -0
- data/README.rdoc +39 -0
- data/Rakefile +81 -0
- data/ext/rubyaudio_ext/extconf.rb +32 -0
- data/ext/rubyaudio_ext/ra_buffer.c +315 -0
- data/ext/rubyaudio_ext/ra_buffer.h +40 -0
- data/ext/rubyaudio_ext/ra_sound.c +506 -0
- data/ext/rubyaudio_ext/ra_sound.h +37 -0
- data/ext/rubyaudio_ext/ra_soundinfo.c +165 -0
- data/ext/rubyaudio_ext/ra_soundinfo.h +25 -0
- data/ext/rubyaudio_ext/rubyaudio_ext.c +92 -0
- data/lib/1.8/rubyaudio_ext.so +0 -0
- data/lib/1.9/rubyaudio_ext.so +0 -0
- data/lib/ruby-audio.rb +10 -0
- data/lib/ruby-audio/buffer.rb +25 -0
- data/lib/ruby-audio/sound.rb +85 -0
- data/lib/ruby-audio/sound_info.rb +66 -0
- data/ruby-audio.gemspec +22 -0
- data/spec/buffer_spec.rb +88 -0
- data/spec/data/what.mp3 +0 -0
- data/spec/data/what.wav +0 -0
- data/spec/data/what2.wav +0 -0
- data/spec/sound_info_spec.rb +49 -0
- data/spec/sound_spec.rb +182 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +11 -0
- metadata +101 -0
@@ -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
|
@@ -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
|
+
}
|
@@ -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
|
@@ -0,0 +1,92 @@
|
|
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", /* 0x010000 */ INT2FIX(SF_FORMAT_WAV));
|
31
|
+
rb_define_const(mRubyAudio, "FORMAT_AIFF", /* 0x020000 */ INT2FIX(SF_FORMAT_AIFF));
|
32
|
+
rb_define_const(mRubyAudio, "FORMAT_AU", /* 0x030000 */ INT2FIX(SF_FORMAT_AU));
|
33
|
+
rb_define_const(mRubyAudio, "FORMAT_RAW", /* 0x040000 */ INT2FIX(SF_FORMAT_RAW));
|
34
|
+
rb_define_const(mRubyAudio, "FORMAT_PAF", /* 0x050000 */ INT2FIX(SF_FORMAT_PAF));
|
35
|
+
rb_define_const(mRubyAudio, "FORMAT_SVX", /* 0x060000 */ INT2FIX(SF_FORMAT_SVX));
|
36
|
+
rb_define_const(mRubyAudio, "FORMAT_NIST", /* 0x070000 */ INT2FIX(SF_FORMAT_NIST));
|
37
|
+
rb_define_const(mRubyAudio, "FORMAT_VOC", /* 0x080000 */ INT2FIX(SF_FORMAT_VOC));
|
38
|
+
rb_define_const(mRubyAudio, "FORMAT_IRCAM", /* 0x0A0000 */ INT2FIX(SF_FORMAT_IRCAM));
|
39
|
+
rb_define_const(mRubyAudio, "FORMAT_W64", /* 0x0B0000 */ INT2FIX(SF_FORMAT_W64));
|
40
|
+
rb_define_const(mRubyAudio, "FORMAT_MAT4", /* 0x0C0000 */ INT2FIX(SF_FORMAT_MAT4));
|
41
|
+
rb_define_const(mRubyAudio, "FORMAT_MAT5", /* 0x0D0000 */ INT2FIX(SF_FORMAT_MAT5));
|
42
|
+
rb_define_const(mRubyAudio, "FORMAT_PVF", /* 0x0E0000 */ INT2FIX(SF_FORMAT_PVF));
|
43
|
+
rb_define_const(mRubyAudio, "FORMAT_XI", /* 0x0F0000 */ INT2FIX(SF_FORMAT_XI));
|
44
|
+
rb_define_const(mRubyAudio, "FORMAT_HTK", /* 0x100000 */ INT2FIX(SF_FORMAT_HTK));
|
45
|
+
rb_define_const(mRubyAudio, "FORMAT_SDS", /* 0x110000 */ INT2FIX(SF_FORMAT_SDS));
|
46
|
+
rb_define_const(mRubyAudio, "FORMAT_AVR", /* 0x120000 */ INT2FIX(SF_FORMAT_AVR));
|
47
|
+
rb_define_const(mRubyAudio, "FORMAT_WAVEX", /* 0x130000 */ INT2FIX(SF_FORMAT_WAVEX));
|
48
|
+
rb_define_const(mRubyAudio, "FORMAT_SD2", /* 0x160000 */ INT2FIX(SF_FORMAT_SD2));
|
49
|
+
rb_define_const(mRubyAudio, "FORMAT_FLAC", /* 0x170000 */ INT2FIX(SF_FORMAT_FLAC));
|
50
|
+
rb_define_const(mRubyAudio, "FORMAT_CAF", /* 0x180000 */ INT2FIX(SF_FORMAT_CAF));
|
51
|
+
#ifdef HAVE_CONST_SF_FORMAT_OGG
|
52
|
+
rb_define_const(mRubyAudio, "FORMAT_OGG", /* 0x200000 */ INT2FIX(SF_FORMAT_OGG));
|
53
|
+
#endif
|
54
|
+
|
55
|
+
// Subtypes from here on
|
56
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_S8", /* 0x0001 */ INT2FIX(SF_FORMAT_PCM_S8));
|
57
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_16", /* 0x0002 */ INT2FIX(SF_FORMAT_PCM_16));
|
58
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_24", /* 0x0003 */ INT2FIX(SF_FORMAT_PCM_24));
|
59
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_32", /* 0x0004 */ INT2FIX(SF_FORMAT_PCM_32));
|
60
|
+
rb_define_const(mRubyAudio, "FORMAT_PCM_U8", /* 0x0005 */ INT2FIX(SF_FORMAT_PCM_U8));
|
61
|
+
rb_define_const(mRubyAudio, "FORMAT_FLOAT", /* 0x0006 */ INT2FIX(SF_FORMAT_FLOAT));
|
62
|
+
rb_define_const(mRubyAudio, "FORMAT_DOUBLE", /* 0x0007 */ INT2FIX(SF_FORMAT_DOUBLE));
|
63
|
+
rb_define_const(mRubyAudio, "FORMAT_ULAW", /* 0x0010 */ INT2FIX(SF_FORMAT_ULAW));
|
64
|
+
rb_define_const(mRubyAudio, "FORMAT_ALAW", /* 0x0011 */ INT2FIX(SF_FORMAT_ALAW));
|
65
|
+
rb_define_const(mRubyAudio, "FORMAT_IMA_ADPCM", /* 0x0012 */ INT2FIX(SF_FORMAT_IMA_ADPCM));
|
66
|
+
rb_define_const(mRubyAudio, "FORMAT_MS_ADPCM", /* 0x0013 */ INT2FIX(SF_FORMAT_MS_ADPCM));
|
67
|
+
rb_define_const(mRubyAudio, "FORMAT_GSM610", /* 0x0020 */ INT2FIX(SF_FORMAT_GSM610));
|
68
|
+
rb_define_const(mRubyAudio, "FORMAT_VOX_ADPCM", /* 0x0021 */ INT2FIX(SF_FORMAT_VOX_ADPCM));
|
69
|
+
rb_define_const(mRubyAudio, "FORMAT_G721_32", /* 0x0030 */ INT2FIX(SF_FORMAT_G721_32));
|
70
|
+
rb_define_const(mRubyAudio, "FORMAT_G723_24", /* 0x0031 */ INT2FIX(SF_FORMAT_G723_24));
|
71
|
+
rb_define_const(mRubyAudio, "FORMAT_G723_40", /* 0x0032 */ INT2FIX(SF_FORMAT_G723_40));
|
72
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_12", /* 0x0040 */ INT2FIX(SF_FORMAT_DWVW_12));
|
73
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_16", /* 0x0041 */ INT2FIX(SF_FORMAT_DWVW_16));
|
74
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_24", /* 0x0042 */ INT2FIX(SF_FORMAT_DWVW_24));
|
75
|
+
rb_define_const(mRubyAudio, "FORMAT_DWVW_N", /* 0x0043 */ INT2FIX(SF_FORMAT_DWVW_N));
|
76
|
+
rb_define_const(mRubyAudio, "FORMAT_DPCM_8", /* 0x0050 */ INT2FIX(SF_FORMAT_DPCM_8));
|
77
|
+
rb_define_const(mRubyAudio, "FORMAT_DPCM_16", /* 0x0051 */ INT2FIX(SF_FORMAT_DPCM_16));
|
78
|
+
#ifdef HAVE_CONST_SF_FORMAT_OGG
|
79
|
+
rb_define_const(mRubyAudio, "FORMAT_VORBIS", /* 0x0060 */ INT2FIX(SF_FORMAT_VORBIS));
|
80
|
+
#endif
|
81
|
+
|
82
|
+
// Endian-ness options
|
83
|
+
rb_define_const(mRubyAudio, "ENDIAN_FILE", /* 0x00000000 */ INT2FIX(SF_ENDIAN_FILE));
|
84
|
+
rb_define_const(mRubyAudio, "ENDIAN_LITTLE", /* 0x10000000 */ INT2FIX(SF_ENDIAN_LITTLE));
|
85
|
+
rb_define_const(mRubyAudio, "ENDIAN_BIG", /* 0x20000000 */ INT2FIX(SF_ENDIAN_BIG));
|
86
|
+
rb_define_const(mRubyAudio, "ENDIAN_CPU", /* 0x30000000 */ INT2FIX(SF_ENDIAN_CPU));
|
87
|
+
|
88
|
+
// Format masks
|
89
|
+
rb_define_const(mRubyAudio, "FORMAT_SUBMASK", /* 0x0000FFFF */ INT2FIX(SF_FORMAT_SUBMASK));
|
90
|
+
rb_define_const(mRubyAudio, "FORMAT_TYPEMASK", /* 0x0FFF0000 */ INT2FIX(SF_FORMAT_TYPEMASK));
|
91
|
+
rb_define_const(mRubyAudio, "FORMAT_ENDMASK", /* 0x30000000 */ INT2FIX(SF_FORMAT_ENDMASK));
|
92
|
+
}
|
Binary file
|
Binary file
|
data/lib/ruby-audio.rb
ADDED
@@ -0,0 +1,25 @@
|
|
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
|
+
include Enumerable
|
14
|
+
|
15
|
+
def each
|
16
|
+
self.size.times do |i|
|
17
|
+
yield self[i]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
[:short, :int, :float, :double].each do |type|
|
22
|
+
eval "def self.#{type}(frames, channels=1); self.new(:#{type}, frames, channels); end"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
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
|