ruby-audio 1.5.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,10 @@
1
+ begin
2
+ # Fat binaries for Windows
3
+ RUBY_VERSION =~ /(\d+.\d+)/
4
+ require "#{$1}/rubyaudio_ext"
5
+ rescue LoadError
6
+ require "rubyaudio_ext"
7
+ end
8
+ require 'ruby-audio/buffer'
9
+ require 'ruby-audio/sound_info'
10
+ require 'ruby-audio/sound'
@@ -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