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/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
@@ -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,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,4 @@
1
+ require 'rubyaudio_ext'
2
+ require 'ruby-audio/buffer'
3
+ require 'ruby-audio/sound_info'
4
+ require 'ruby-audio/sound'
@@ -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