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.
@@ -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