ffi-portaudio 0.1.0 → 0.1.1

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,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: