ruby-audio 0.2.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,90 +0,0 @@
1
- // TODO: sf_command,
2
- %module "sndfile"
3
- %{
4
- #include <sndfile.h>
5
- #include <narray.h>
6
- %}
7
-
8
- // this bit brought to you by stdio.h
9
- #ifndef SEEK_SET
10
- #define SEEK_SET 0 /* set file offset to offset */
11
- #endif
12
- #ifndef SEEK_CUR
13
- #define SEEK_CUR 1 /* set file offset to current plus offset */
14
- #endif
15
- #ifndef SEEK_END
16
- #define SEEK_END 2 /* set file offset to EOF plus offset */
17
- #endif
18
-
19
- %include "typemaps.i"
20
- %typemap(out) int sf_format_check {
21
- if ($1)
22
- $result = Qtrue;
23
- else
24
- $result = Qfalse;
25
- }
26
-
27
- %typemap(out) sf_count_t {
28
- $result = INT2NUM($1);
29
- }
30
- %typemap(in) sf_count_t {
31
- $1 = (sf_count_t) NUM2INT($input);
32
- }
33
-
34
- // We have to do this or when a function like sf_get_string returns NULL it
35
- // will raise an exception when trying to create the string.
36
- %typemap(out) const char *{
37
- if ($1 == 0)
38
- $result = Qnil;
39
- else
40
- $result = rb_str_new2($1);
41
- }
42
-
43
- %typemap(in) (short *ptr, sf_count_t),
44
- (const short *ptr, sf_count_t)
45
- {
46
- if (!(NA_IsNArray($input) && NA_TYPE($input) == NA_SINT))
47
- rb_raise(rb_eArgError, "Expected NArray.sint");
48
- $1 = NA_PTR_TYPE($input, $1_type);
49
- $2 = NA_TOTAL($input);
50
- }
51
- %typemap(in) (int *ptr, sf_count_t),
52
- (const int *ptr, sf_count_t)
53
- {
54
- if (!(NA_IsNArray($input) && NA_TYPE($input) == NA_LINT))
55
- rb_raise(rb_eArgError, "Expected NArray.int");
56
- $1 = NA_PTR_TYPE($input, $1_type);
57
- $2 = NA_TOTAL($input);
58
- }
59
- %typemap(in) (float *ptr, sf_count_t),
60
- (const float *ptr, sf_count_t)
61
- {
62
- if (!(NA_IsNArray($input) && NA_TYPE($input) == NA_SFLOAT))
63
- rb_raise(rb_eArgError, "Expected NArray.sfloat");
64
- $1 = NA_PTR_TYPE($input, $1_type);
65
- $2 = NA_TOTAL($input);
66
- }
67
- %typemap(in) (double *ptr, sf_count_t),
68
- (const double *ptr, sf_count_t)
69
- {
70
- if (!(NA_IsNArray($input) && NA_TYPE($input) == NA_DFLOAT))
71
- rb_raise(rb_eArgError, "Expected NArray.float");
72
- $1 = NA_PTR_TYPE($input, $1_type);
73
- $2 = NA_TOTAL($input);
74
- }
75
-
76
- %typemap(in) (void *data, int datasize), (void *ptr, sf_count_t),
77
- (const void *ptr, sf_count_t)
78
- {
79
- if (!NA_IsNArray($input))
80
- rb_raise(rb_eArgError, "Expected NArray");
81
- $1 = NA_STRUCT($input)->ptr;
82
- $2 = NA_TOTAL($input) * na_sizeof[NA_TYPE($input)];
83
- }
84
-
85
-
86
- // sf_perror and sf_error_str are deprecated. sf_error_str probably doesn't
87
- // work at all.
88
-
89
- %include "sndfile.h"
90
- // vim: filetype=c
data/lib/audio.rb DELETED
@@ -1,134 +0,0 @@
1
- require 'rubygems'
2
- require 'narray'
3
-
4
- # TODO: libsamplerate, portaudio
5
- module Audio
6
-
7
- # A Sound is a NArray with some audio convenience methods. It should always
8
- # have the shape <tt>[frames,channels]</tt>. (Even when m=1)
9
- #
10
- # *Notice* for NArray users: because most audio libraries do not agree with
11
- # NArray on type names, Sound.float has a different meaning than
12
- # NArray.float. Also, the shape of a new Sound is different than you might
13
- # expect:
14
- # s = Sound.float(10)
15
- # n = NArray.float(10)
16
- # s.shape #=> [10,1]
17
- # n.shape #=> [10]
18
- # s.typecode #=> 4
19
- # n.typecode #=> 5
20
- class Sound < NArray
21
-
22
- # Mapping from typecode to type symbols
23
- TYPES = [nil,:char,:short,:long,:float,:double]
24
-
25
- # typecode:: Same as NArray, or a member of TYPES
26
- # frames:: Number of frames
27
- # channels:: Number of channels
28
- #
29
- # Note that the resulting shape is always [frames,channels].
30
- def self.new(typecode,frames,channels=1)
31
- case typecode
32
- when String, Symbol
33
- typecode = TYPES.index(typecode.to_sym)
34
- end
35
- super(typecode,frames,channels)
36
- end
37
-
38
- # One of TYPES
39
- def type
40
- TYPES[typecode]
41
- end
42
-
43
- # The number of frames
44
- def frames
45
- self.shape[0]
46
- end
47
-
48
- # The number of channels
49
- def channels
50
- self.shape[1]
51
- end
52
-
53
- # Returns a new Sound with the data from channel i
54
- def channel(i)
55
- self[true,i]
56
- end
57
-
58
- # A frame, i.e. an array containing the samples at position i from each
59
- # channel. For a two-channel sound:
60
- # sound.frame(i) #=> [0.42, 0.12]
61
- #
62
- # You may prefer to do this the NArray way: s[i,false]
63
- def frame(i)
64
- unless (0...frames).include? i
65
- raise IndexError, "Index out of range"
66
- end
67
- self[i,false]
68
- end
69
-
70
- # For a two-channel sound:
71
- # s.set_frame(i,[0.42,0.24])
72
- # s.set_frame(i,0.42) #=> s.set_frame(i,[0.42,0.42])
73
- #
74
- # You may prefer to do this the NArray way: s[i,false] = val
75
- def set_frame(i,val)
76
- self[i,false] = val
77
- end
78
-
79
- def each_frame
80
- frames.times do |i|
81
- yield frame(i)
82
- end
83
- end
84
-
85
- # Return a Sound with the channels interleaved.
86
- # Sound[[0,1],[2,3]].interleaved #=> Sound[[0,2,1,3]]
87
- def interleave
88
- self.transpose(1,0).reshape!(self.size,1)
89
- end
90
- alias_method :interleaved, :interleave
91
-
92
- # Fill this Sound's channels with deinterleaved data.
93
- # Sound[[0,0],[0,0]].interleaved = NArray[0,2,1,3] #=> Sound[[0,1],[2,3]]
94
- def interleave=(o)
95
- self[] = o.reshape(channels,frames).transpose(1,0)
96
- self
97
- end
98
- alias_method :interleaved=, :interleave=
99
-
100
-
101
- # Creates a new Sound with the specified number of channels from the
102
- # interleaved data in narray. narray should be evenly divisible by
103
- # channels.
104
- def self.deinterleave(narray,channels)
105
- unless narray.size % channels == 0
106
- raise ArgumentError, "narray not evenly divisible by channels"
107
- end
108
- frames = narray.size/channels
109
- s = Sound.new(narray.typecode,frames,channels)
110
- s.interleaved = narray
111
- s
112
- end
113
- def deinterleave(channels)
114
- self.class.deinterleave(self,channels)
115
- end
116
- def deinterleave!(channels)
117
- s = deinterleave(channels)
118
- reshape!(*s.shape)
119
- self[] = s
120
- end
121
-
122
- %w{char short long float double}.each_with_index do |t,i|
123
- eval "def self.#{t}(frames,channels=1); self.new(#{i+1},frames,channels); end"
124
- end
125
-
126
- # alias class methods
127
- class << self
128
- alias_method :byte, :char
129
- alias_method :sint, :short
130
- alias_method :int, :long
131
- alias_method :sfloat, :float
132
- end
133
- end
134
- end
data/lib/audio/sndfile.rb DELETED
@@ -1,156 +0,0 @@
1
- require 'audio'
2
- require 'sndfile.so'
3
-
4
- module Audio
5
- # libsndfile[http://www.mega-nerd.com/libsndfile/]
6
- #
7
- # = Synopsis
8
- # require 'audio/sndfile'
9
- #
10
- # Audio::Soundfile.open('chunky_bacon.wav') do |sf|
11
- # sound = sf.readf_float(sf.frames)
12
- # puts "Maximum amplitude: #{sound.abs.max}"
13
- # end
14
- #
15
- # = Details
16
- # Refer to the libsndfile api[http://www.mega-nerd.com/libsndfile/api.html].
17
- #
18
- # Usage is quite straightforward: drop the +sf_+ prefix, omit the
19
- # <tt>SNDFILE*</tt> parameter, and use Sound or Numeric instead of
20
- # (pointer, size) pairs. So, if you have a Soundfile object named +sf+, then
21
- # sf_read_float(SNDFILE, float *ptr, sf_count_t items)
22
- # becomes
23
- # buf = Sound.float(items)
24
- # sf.read_float(buf)
25
- # or
26
- # buf = sf.read_float(items) # creates a new Sound
27
- #
28
- # Exceptions to this pattern are documented below.
29
- #
30
- # Constants are accessed as <tt>Soundfile::SF_FORMAT_WAV</tt>
31
- class Soundfile
32
- # SF_INFO
33
- attr :info
34
- attr_reader :mode
35
-
36
- # mode:: One of %w{r w rw}
37
- # info:: Instance of SF_INFO or nil
38
- def initialize(path, mode='r', info=nil)
39
- if info.nil?
40
- info = SF_INFO.new
41
- end
42
-
43
- modes = {:r => SFM_READ, :w => SFM_WRITE, :rw => SFM_RDWR}
44
- unless Numeric === mode
45
- mode = modes[mode.to_sym]
46
- end
47
- unless [SFM_READ, SFM_WRITE, SFM_RDWR].include? mode
48
- raise ArgumentError, "Invalid mode"
49
- end
50
-
51
- sf = Sndfile.sf_open(path.to_s, mode, info)
52
- @sf = sf
53
- @info = info
54
- @mode = modes.invert[mode]
55
- if block_given?
56
- yield self
57
- self.close
58
- end
59
- end
60
-
61
- class << self
62
- alias_method :open, :new
63
- end
64
-
65
- def frames
66
- @info.frames
67
- end
68
- def samplerate
69
- @info.samplerate
70
- end
71
- def channels
72
- @info.channels
73
- end
74
- def format
75
- @info.format
76
- end
77
- def sections
78
- @info.sections
79
- end
80
- def seekable
81
- @info.seekable
82
- end
83
-
84
- # The following are equivalent:
85
- # sf_format_check(info) /* C */
86
- # sf.format_check # ruby
87
- def format_check
88
- Sndfile.sf_format_check(@info)
89
- end
90
-
91
- TYPES = [nil,:char,:short,:int,:float,:double] #:nodoc:
92
-
93
- # Automagic read method. Type is autodetected.
94
- def read(na)
95
- sym = "read_#{TYPES[na.typecode]}".to_sym
96
- self.send sym, na
97
- end
98
-
99
- # Automagic write method. Type is autodetected.
100
- def write(na)
101
- sym = "write_#{TYPES[na.typecode]}".to_sym
102
- self.send sym, na
103
- end
104
-
105
- %w{read readf}.each do |r|
106
- %w{short int float double}.each do |t|
107
- tc = TYPES.index(t.to_sym)
108
- c = ', channels' if r == 'readf'
109
- cmd = "#{r}_#{t}"
110
- eval <<-EOF
111
- def #{cmd}(arg)
112
- if Numeric === arg
113
- na = NArray.new(#{tc}, arg#{c})
114
- n = Sndfile.sf_#{cmd}(@sf, na)
115
- Sound.deinterleave(na, channels)
116
- else
117
- na = arg
118
- n = Sndfile.sf_#{cmd}(@sf, na)
119
- na.deinterleave!(channels)
120
- n
121
- end
122
- end
123
- EOF
124
- end
125
- end
126
-
127
- %w{write writef}.each do |w|
128
- %w{short int float double}.each do |t|
129
- cmd = "#{w}_#{t}"
130
- eval <<-EOF
131
- def #{cmd}(sound)
132
- raise "Format check failed: \#{perror}" unless format_check
133
- Sndfile.sf_#{cmd}(@sf, sound.interleave)
134
- end
135
- EOF
136
- end
137
- end
138
-
139
- def method_missing(name, *args) #:nodoc:
140
- begin
141
- Sndfile.send "sf_#{name}".to_sym, @sf, *args
142
- rescue NameError
143
- super
144
- end
145
- end
146
-
147
- def self.const_missing(sym) #:nodoc:
148
- begin
149
- Sndfile.const_get(sym)
150
- rescue NameError
151
- super
152
- end
153
- end
154
- end
155
- end
156
-
data/test/test_audio.rb DELETED
@@ -1,82 +0,0 @@
1
- require 'test/unit'
2
- require 'audio'
3
-
4
- class AudioTest < Test::Unit::TestCase
5
- include Audio
6
- def test_sound
7
- %w{char short long float double}.each do |t|
8
- eval "s = Sound.#{t}(10); assert_equal :#{t}, s.type"
9
- end
10
- s = Sound.float(6).indgen!
11
- assert_equal [6,1], s.shape
12
- assert_equal 1, s.channels
13
- assert_equal 6, s.frames
14
- s.reshape!(3,2)
15
- assert_equal 2, s.channels
16
- assert_equal 3, s.frames
17
- assert_equal [[0.0,3.0,1.0,4.0,2.0,5.0]], s.interleave.to_a
18
- assert_equal 6, s.size
19
-
20
- s = Sound.byte(10); assert_equal :char, s.type
21
- s = Sound.sint(10); assert_equal :short, s.type
22
- s = Sound.int(10); assert_equal :long, s.type
23
- s = Sound.sfloat(10); assert_equal :float, s.type
24
-
25
- s = Sound.sfloat(10)
26
- assert_equal 10, s.size
27
- assert_equal 10, s.frames
28
- assert_equal 1, s.channels
29
- assert_equal :float, s.type
30
- assert_kind_of NArray, s
31
- s.channels.times do |i|
32
- c = s.channel(i)
33
- assert_kind_of NArray, c
34
- assert_instance_of Sound, c
35
- assert_equal 10, c.size
36
- end
37
-
38
- s = Sound.double(10,2)
39
- assert_equal 2, s.channels
40
- assert_equal 10, s.frames
41
-
42
- c = s.channel(1)
43
- assert_instance_of Sound, c
44
- assert_equal 10, c.size
45
-
46
- s.each_frame do |a|
47
- assert_instance_of Sound, a
48
- assert_kind_of Numeric, a[0]
49
- assert_kind_of Numeric, a[1]
50
- end
51
-
52
- # test new
53
- s = Sound.new(4,10)
54
- assert_equal [10,1], s.shape
55
- assert_equal 10, s.size
56
- assert_equal 4, s.typecode
57
- assert_equal :float, s.type
58
- assert_equal 10, s.frames
59
- assert_equal 1, s.channels
60
-
61
- s = Sound.new(:long,10)
62
- assert_equal [10,1], s.shape
63
- assert_equal 10, s.size
64
- assert_equal 3, s.typecode
65
- assert_equal :long, s.type
66
- assert_equal 10, s.frames
67
- assert_equal 1, s.channels
68
- end
69
-
70
- def test_interleave
71
- s = Sound.float(2,2).indgen!
72
- i = s.interleave
73
- assert_equal s[0,0], i[0]
74
- assert_equal s[0,1], i[1]
75
-
76
- s2 = Sound.deinterleave(i,2)
77
- assert_equal s, s2
78
-
79
- s2.interleave = i
80
- assert_equal s, s2
81
- end
82
- end