ffi-portaudio 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  = ffi-portaudio
2
2
 
3
- * http://github.com/nanki/ffi-chm
3
+ * http://github.com/nanki/ffi-portaudio
4
4
 
5
5
  Ruby bindings for PortAudio.
6
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -0,0 +1,138 @@
1
+ require 'ffi-portaudio'
2
+
3
+ include FFI::PortAudio
4
+
5
+ # from https://github.com/corbanbrook/fourier_transform
6
+ class FourierTransform
7
+ attr_reader :spectrum, :bandwidth, :samplerate, :buffersize
8
+
9
+ def initialize buffersize, samplerate
10
+ @buffersize = buffersize
11
+ @samplerate = samplerate
12
+ @bandwidth = (2.0 / @buffersize) * (@samplerate / 2.0)
13
+ @spectrum = Array.new
14
+
15
+ build_reverse_table
16
+ build_trig_tables
17
+ end
18
+
19
+ def build_reverse_table
20
+ @reverse = Array.new(@buffersize)
21
+ @reverse[0] = 0;
22
+
23
+ limit = 1
24
+ bit = @buffersize >> 1
25
+
26
+ while (limit < @buffersize )
27
+ (0...limit).each do |i|
28
+ @reverse[i + limit] = @reverse[i] + bit
29
+ end
30
+
31
+ limit = limit << 1
32
+ bit = bit >> 1
33
+ end
34
+ end
35
+
36
+ def build_trig_tables
37
+ @sin_lookup = Array.new(@buffersize)
38
+ @cos_lookup = Array.new(@buffersize)
39
+ (0...@buffersize).each do |i|
40
+ @sin_lookup[i] = Math.sin(- Math::PI / i);
41
+ @cos_lookup[i] = Math.cos(- Math::PI / i);
42
+ end
43
+ end
44
+
45
+ def fft(buffer)
46
+ raise Exception if buffer.length % 2 != 0
47
+
48
+ real = Array.new(buffer.length)
49
+ imag = Array.new(buffer.length)
50
+
51
+ (0...buffer.length).each do |i|
52
+ real[i] = buffer[@reverse[i]]
53
+ imag[i] = 0.0
54
+ end
55
+
56
+ halfsize = 1
57
+ while halfsize < buffer.length
58
+ phase_shift_step_real = @cos_lookup[halfsize]
59
+ phase_shift_step_imag = @sin_lookup[halfsize]
60
+ current_phase_shift_real = 1.0
61
+ current_phase_shift_imag = 0.0
62
+ (0...halfsize).each do |fft_step|
63
+ i = fft_step
64
+ while i < buffer.length
65
+ off = i + halfsize
66
+ tr = (current_phase_shift_real * real[off]) - (current_phase_shift_imag * imag[off])
67
+ ti = (current_phase_shift_real * imag[off]) + (current_phase_shift_imag * real[off])
68
+ real[off] = real[i] - tr
69
+ imag[off] = imag[i] - ti
70
+ real[i] += tr
71
+ imag[i] += ti
72
+
73
+ i += halfsize << 1
74
+ end
75
+ tmp_real = current_phase_shift_real
76
+ current_phase_shift_real = (tmp_real * phase_shift_step_real) - (current_phase_shift_imag * phase_shift_step_imag)
77
+ current_phase_shift_imag = (tmp_real * phase_shift_step_imag) + (current_phase_shift_imag * phase_shift_step_real)
78
+ end
79
+
80
+ halfsize = halfsize << 1
81
+ end
82
+
83
+ (0...buffer.length/2).each do |i|
84
+ @spectrum[i] = 2 * Math.sqrt(real[i] ** 2 + imag[i] ** 2) / buffer.length
85
+ end
86
+
87
+ @spectrum
88
+ end
89
+ end
90
+
91
+ WINDOW = 1024
92
+
93
+ class FFTStream < Stream
94
+ def initialize
95
+ @max = 1
96
+ @fourier = FourierTransform.new(WINDOW, 44100)
97
+ end
98
+
99
+ def process(input, output, frameCount, timeInfo, statusFlags, userData)
100
+ @fourier.fft input.read_array_of_int16(frameCount)
101
+
102
+ print "\e[2J\e[H"
103
+ puts "Spectrum"
104
+ @fourier.spectrum[0, WINDOW/16].each_slice(2) do |a|
105
+ sum = a.inject(0, :+)
106
+ @max = [@max, sum].max
107
+ s = "*" * (sum * 50 / @max).to_i
108
+
109
+ [[0, 36], [5, 32], [40, 31]].reverse.each do |i, color|
110
+ s[i] = "\e[#{color}m" if s[i]
111
+ end
112
+ puts s
113
+ print "\e[0m"
114
+ end
115
+
116
+ :paContinue
117
+ end
118
+ end
119
+
120
+ API.Pa_Initialize
121
+
122
+ input = API::PaStreamParameters.new
123
+ input[:device] = API.Pa_GetDefaultInputDevice
124
+ input[:channelCount] = 1
125
+ input[:sampleFormat] = API::Int16
126
+ input[:suggestedLatency] = 0
127
+ input[:hostApiSpecificStreamInfo] = nil
128
+
129
+ stream = FFTStream.new
130
+ stream.open(input, nil, 44100, WINDOW)
131
+ stream.start
132
+
133
+ at_exit {
134
+ stream.close
135
+ API.Pa_Terminate
136
+ }
137
+
138
+ loop { sleep 1 }
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ffi-portaudio}
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{nanki}]
12
+ s.date = %q{2011-09-24}
13
+ s.description = %q{Ruby bindings for PortAudio.}
14
+ s.email = %q{nanki@dotswitch.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "LICENSE.txt",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "examples/spectrum.rb",
27
+ "ffi-portaudio.gemspec",
28
+ "lib/ffi-portaudio.rb",
29
+ "lib/ffi-portaudio/api.rb",
30
+ "lib/ffi-portaudio/const.rb",
31
+ "lib/ffi-portaudio/enum.rb",
32
+ "lib/ffi-portaudio/stream.rb",
33
+ "lib/ffi-portaudio/struct.rb",
34
+ "test/helper.rb",
35
+ "test/test_ffi-portaudio.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/nanki/ffi-portaudio}
38
+ s.licenses = [%q{MIT}]
39
+ s.require_paths = [%q{lib}]
40
+ s.rubygems_version = %q{1.8.6}
41
+ s.summary = %q{Ruby bindings for PortAudio.}
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<ffi>, [">= 0"])
48
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
49
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
50
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
51
+ s.add_development_dependency(%q<rcov>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<ffi>, [">= 0"])
54
+ s.add_dependency(%q<shoulda>, [">= 0"])
55
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
56
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
57
+ s.add_dependency(%q<rcov>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<ffi>, [">= 0"])
61
+ s.add_dependency(%q<shoulda>, [">= 0"])
62
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
63
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
64
+ s.add_dependency(%q<rcov>, [">= 0"])
65
+ end
66
+ end
67
+
@@ -4,7 +4,7 @@ class FFI::PortAudio::Stream
4
4
  def open(input, output, freq, frames=API::FramesPerBufferUnspecified, flags=API::NoFlag, userdata=nil)
5
5
  @input, @output, @freq, @frames, @flags, @userdata = input, output, freq, frames, flags, userdata
6
6
  @stream = FFI::Buffer.new :pointer
7
- API.Pa_OpenStream(@stream, @input, @output, @freq, @frames, @flags, method(:process), @userdata)
7
+ API.Pa_OpenStream(@stream, @input, @output, @freq, @frames, @flags, @method = method(:process), @userdata)
8
8
  end
9
9
 
10
10
  def process(input, output, frameCount, timeInfo, statusFlags, userData);end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-portaudio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-09-24 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ffi
16
- requirement: &70202622192620 !ruby/object:Gem::Requirement
16
+ requirement: &70163434899500 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70202622192620
24
+ version_requirements: *70163434899500
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: shoulda
27
- requirement: &70202622190760 !ruby/object:Gem::Requirement
27
+ requirement: &70163434898380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70202622190760
35
+ version_requirements: *70163434898380
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bundler
38
- requirement: &70202622189900 !ruby/object:Gem::Requirement
38
+ requirement: &70163434897400 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.0.0
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70202622189900
46
+ version_requirements: *70163434897400
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: jeweler
49
- requirement: &70202622188400 !ruby/object:Gem::Requirement
49
+ requirement: &70163434896680 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.6.4
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70202622188400
57
+ version_requirements: *70163434896680
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rcov
60
- requirement: &70202622186760 !ruby/object:Gem::Requirement
60
+ requirement: &70163434895640 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70202622186760
68
+ version_requirements: *70163434895640
69
69
  description: Ruby bindings for PortAudio.
70
70
  email: nanki@dotswitch.net
71
71
  executables: []
@@ -80,6 +80,8 @@ files:
80
80
  - README.rdoc
81
81
  - Rakefile
82
82
  - VERSION
83
+ - examples/spectrum.rb
84
+ - ffi-portaudio.gemspec
83
85
  - lib/ffi-portaudio.rb
84
86
  - lib/ffi-portaudio/api.rb
85
87
  - lib/ffi-portaudio/const.rb
@@ -103,7 +105,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
105
  version: '0'
104
106
  segments:
105
107
  - 0
106
- hash: -1876936708131014168
108
+ hash: 4355147882575876010
107
109
  required_rubygems_version: !ruby/object:Gem::Requirement
108
110
  none: false
109
111
  requirements: