easy_audio 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/LICENSE +24 -0
- data/README.md +57 -0
- data/Rakefile +35 -0
- data/easy_audio.gemspec +15 -0
- data/examples/increase_frequency.rb +7 -0
- data/examples/one_second_sine.rb +5 -0
- data/examples/record_microphone_delay.rb +6 -0
- data/lib/easy_audio.rb +237 -0
- data/samus.json +44 -0
- metadata +69 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 40a26cab3088ab5982f88fcdae9d10b1f89adbba
|
4
|
+
data.tar.gz: 96c4ec815952cc8dca68bd8392612a6654a61d3c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a5aafb3994e2f8775cf7df6759e0ca8bf8d3e353afb6879892a40fb6e4bd9bea34f640d73d47f98dcb00d93e3b0049a5d190072bcb27f8c4d7c394a956429f1b
|
7
|
+
data.tar.gz: 9cb68b967815c5e07abcea57239d25ed5fef403e223a0e1d5c2e3db789ed6ff9b77ef72508a1ada2d77bba753c9818c59f5d309398ae490c240873aedb46d92a
|
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2014, Loren Segal
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
* Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
* Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
* Neither the name of the copyright holder nor the
|
12
|
+
names of its contributors may be used to endorse or promote products
|
13
|
+
derived from this software without specific prior written permission.
|
14
|
+
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL LOREN SEGAL BE LIABLE FOR ANY
|
19
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
24
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# EasyAudio
|
2
|
+
|
3
|
+
EasyAudio is a simplified wrapper for the [portaudio][portaudio] library, which
|
4
|
+
allows to you play or record audio directly from your sound card.
|
5
|
+
|
6
|
+
## Installing
|
7
|
+
|
8
|
+
```sh
|
9
|
+
$ gem install easy_audio
|
10
|
+
```
|
11
|
+
|
12
|
+
Note: if you are on a Linux or Windows machine you will need to manually
|
13
|
+
install portaudio to a location in your library paths. The gem will attempt
|
14
|
+
to install this automatically on OS X through [Homebrew][brew].
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
|
18
|
+
Here's how you can easily play a sine wave at 440hz:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
require 'easy_audio'
|
22
|
+
|
23
|
+
EasyAudio.easy_open(&EasyAudio::Waveforms::SINE)
|
24
|
+
sleep 2 # play for 2 seconds
|
25
|
+
```
|
26
|
+
|
27
|
+
Here's a triangle wave that increases its frequency over 3 seconds:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'easy_audio'
|
31
|
+
|
32
|
+
stream = EasyAudio.easy_open(freq: 220, &EasyAudio::Waveforms::TRIANGLE)
|
33
|
+
Thread.new { loop { stream.frequency += 50; sleep 0.2 } }
|
34
|
+
sleep 3
|
35
|
+
```
|
36
|
+
|
37
|
+
Record audio from your microphone and play it back a second later:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
require 'easy_audio'
|
41
|
+
|
42
|
+
EasyAudio.easy_open(in: true, out: true, latency: 1.0) { current_sample }
|
43
|
+
sleep 10 # for 10 seconds
|
44
|
+
```
|
45
|
+
|
46
|
+
## Documentation
|
47
|
+
|
48
|
+
See the API documentation on [rubydoc.info][docs].
|
49
|
+
|
50
|
+
## License
|
51
|
+
|
52
|
+
EasyAudio is copyright © 2014 by Loren Segal and licensed under the BSD
|
53
|
+
license. See the LICENSE file for more information.
|
54
|
+
|
55
|
+
[portaudio]: http://portaudio.com
|
56
|
+
[brew]: http://brew.sh
|
57
|
+
[docs]: http://rubydoc.info/gems/easy_audio/frames
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
task :default => :install
|
2
|
+
|
3
|
+
task :install do
|
4
|
+
have_portaudio = false
|
5
|
+
print "Checking for portaudio..."
|
6
|
+
begin
|
7
|
+
require "ffi-portaudio"
|
8
|
+
have_portaudio = true
|
9
|
+
puts " yes."
|
10
|
+
rescue LoadError
|
11
|
+
puts "no."
|
12
|
+
end
|
13
|
+
|
14
|
+
if !have_portaudio
|
15
|
+
success = false
|
16
|
+
puts "Portaudio is missing, attempting to install..."
|
17
|
+
|
18
|
+
if RbConfig::CONFIG['host_os'].match(/darwin/)
|
19
|
+
puts "Detected Mac OS X, installing with Homebrew..."
|
20
|
+
begin
|
21
|
+
sh "brew install portaudio"
|
22
|
+
success = true if $? == 0
|
23
|
+
rescue
|
24
|
+
puts "Could not install portaudio. Do you have Homebrew installed?"
|
25
|
+
end
|
26
|
+
else
|
27
|
+
puts "Only OS X installation currently supported. Install portaudio " +
|
28
|
+
"from http://portaudio.com and reinstall."
|
29
|
+
end
|
30
|
+
|
31
|
+
if success
|
32
|
+
puts "Installed portaudio. Continuing installation of easy_audio..."
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/easy_audio.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "easy_audio"
|
3
|
+
s.summary = "EasyAudio is a simplified wrapper for the portaudio library."
|
4
|
+
s.description = "EasyAudio allows you to play or record from your sound card."
|
5
|
+
s.version = File.read("lib/easy_audio.rb")[/VERSION = "(.+?)"/, 1]
|
6
|
+
s.author = "Loren Segal"
|
7
|
+
s.email = "lsegal@soen.ca"
|
8
|
+
s.homepage = "http://github.com/lsegal/easy_audio"
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.files = `git ls-files`.split(/\s+/)
|
11
|
+
s.extensions = ["Rakefile"]
|
12
|
+
s.license = "BSD"
|
13
|
+
|
14
|
+
s.add_runtime_dependency "ffi-portaudio", "~> 0.0"
|
15
|
+
end
|
data/lib/easy_audio.rb
ADDED
@@ -0,0 +1,237 @@
|
|
1
|
+
require 'ffi-portaudio'
|
2
|
+
|
3
|
+
# Easy Audio is a library to simplify the Portaudio interface
|
4
|
+
# @see http://portaudio.com
|
5
|
+
module EasyAudio
|
6
|
+
VERSION = "0.1.0"
|
7
|
+
|
8
|
+
# Represents a single buffer passed to the {Stream} process block
|
9
|
+
class StreamPacket < Struct.new(:samples, :num_samples, :time_info, :status_info, :user_data)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Represents a single audio input/output stream. See {#initialize} for usage
|
13
|
+
# examples.
|
14
|
+
class Stream < FFI::PortAudio::Stream
|
15
|
+
include FFI::PortAudio
|
16
|
+
|
17
|
+
# @!method start
|
18
|
+
# Starts processing the stream.
|
19
|
+
|
20
|
+
# @!method stop
|
21
|
+
# Stops processing the stream.
|
22
|
+
|
23
|
+
# Creates a new stream for processing audio. Call {#start} to start
|
24
|
+
# processing.
|
25
|
+
#
|
26
|
+
# @option opts :sample_rate [Fixnum] (44100) the sample rate to play at.
|
27
|
+
# @option opts :frame_size [Fixnum] (256) the number of frames per buffer.
|
28
|
+
# @option opts :in [Boolean] whether to use the default input device.
|
29
|
+
# @option opts :out [Boolean] whether to use the default output device.
|
30
|
+
# @option opts :in_chans [Fixnum] (2) the number of channels to process from
|
31
|
+
# the input device.
|
32
|
+
# @option opts :out_chans [Fixnum] (2) the number of channels to process
|
33
|
+
# from the output device.
|
34
|
+
# @option opts :latency [Float] (0.0) the default latency for processing.
|
35
|
+
# @yield [buffer] runs the provided block against the sample buffer data
|
36
|
+
# @yieldparam buffer [StreamPacket] the sample data to process
|
37
|
+
# @yieldreturn [Array<Float>] return an array of interlaced floating points
|
38
|
+
# for each channel in {#output_channels}.
|
39
|
+
# @example Process audio from input (microphone) and playback on output
|
40
|
+
# EasyAudio::Stream.new(in: true, out: true) do |buffer|
|
41
|
+
# buffer.samples # echos the stream to output
|
42
|
+
# end
|
43
|
+
# @see #start
|
44
|
+
def initialize(opts = {}, &block)
|
45
|
+
pa_start
|
46
|
+
|
47
|
+
@fn = block
|
48
|
+
@sample_rate = opts[:sample_rate] || 44100
|
49
|
+
@frame_size = opts[:frame_size] || 256
|
50
|
+
@input_channels = opts[:in_chans] || 1
|
51
|
+
@output_channels = opts[:out_chans] || 1
|
52
|
+
@latency = opts[:latency] || 0.01
|
53
|
+
|
54
|
+
input, output = nil, nil
|
55
|
+
if opts[:in] || opts[:in_chans]
|
56
|
+
device = API.Pa_GetDefaultInputDevice
|
57
|
+
input = stream_for(device, @input_channels, @latency)
|
58
|
+
end
|
59
|
+
|
60
|
+
if opts[:out] || opts[:out_chans] || !input
|
61
|
+
device = API.Pa_GetDefaultOutputDevice
|
62
|
+
output = stream_for(device, @output_channels, @latency)
|
63
|
+
end
|
64
|
+
|
65
|
+
open(input, output, @sample_rate, @frame_size)
|
66
|
+
end
|
67
|
+
|
68
|
+
attr_accessor :fn, :sample_rate, :frame_size
|
69
|
+
attr_reader :input_channels, :output_channels, :latency
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# Don't override this function. Pass in a `process` Proc object to
|
74
|
+
# {#initialize} instead.
|
75
|
+
def process(input, output, frames, time_info, status, user_data)
|
76
|
+
result = run_process(input, output, frames, time_info, status, user_data)
|
77
|
+
unless Array === result
|
78
|
+
result = Array.new(frames * @output_channels).map {0}
|
79
|
+
end
|
80
|
+
|
81
|
+
output.write_array_of_float(result)
|
82
|
+
:paContinue
|
83
|
+
rescue => e
|
84
|
+
puts e.message + "\n " + e.backtrace.join("\n ")
|
85
|
+
:paAbort
|
86
|
+
end
|
87
|
+
|
88
|
+
def run_process(input, output, frames, time_info, status, user_data)
|
89
|
+
inbuf = nil
|
90
|
+
if input.address != 0
|
91
|
+
inbuf = input.read_array_of_float(frames * @input_channels)
|
92
|
+
end
|
93
|
+
|
94
|
+
buffer = StreamPacket.new(inbuf, frames, time_info, status, user_data)
|
95
|
+
@fn ? @fn.call(buffer) : nil
|
96
|
+
end
|
97
|
+
|
98
|
+
def stream_for(device, channels, latency)
|
99
|
+
API::PaStreamParameters.new.tap do |stream|
|
100
|
+
info = API.Pa_GetDeviceInfo(device)
|
101
|
+
stream[:device] = device
|
102
|
+
stream[:suggestedLatency] = latency
|
103
|
+
stream[:hostApiSpecificStreamInfo] = nil
|
104
|
+
stream[:channelCount] = channels
|
105
|
+
stream[:sampleFormat] = API::Float32
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def pa_start
|
110
|
+
return if @@stream_started
|
111
|
+
API.Pa_Initialize
|
112
|
+
at_exit { API.Pa_Terminate }
|
113
|
+
@@stream_started = true
|
114
|
+
end
|
115
|
+
|
116
|
+
@@stream_started = false
|
117
|
+
end
|
118
|
+
|
119
|
+
# A simplified {Stream} class whose processor block only processes a single
|
120
|
+
# frame at a time. See {Waveforms} for a set of pre-fabricated EasyStream
|
121
|
+
# processor blocks for examples of how to process a single stream.
|
122
|
+
#
|
123
|
+
# Note that instead of passing state information as an argument to the block,
|
124
|
+
# state is instead stored in the class itself, and the block is instance
|
125
|
+
# evaluated. This makes it a bit slower to process, but much more convenient
|
126
|
+
# for creating blocks.
|
127
|
+
#
|
128
|
+
# See {#initialize} for usage examples.
|
129
|
+
class EasyStream < Stream
|
130
|
+
|
131
|
+
# {include:Stream#initialize}
|
132
|
+
#
|
133
|
+
# @option (see Stream#initialize)
|
134
|
+
# @option opts :freq [Float] (440.0) the frequency to generate {#step}
|
135
|
+
# values at.
|
136
|
+
# @option opts :amp [Float] (1.0) the amplitude to scale values to.
|
137
|
+
# @yield a process block that processes one frame at a time.
|
138
|
+
# @yieldreturn [Array<Float>] return an array of interlaced floating points
|
139
|
+
# for each channel in {#output_channels}.
|
140
|
+
# @example Process audio from input (microphone) and playback on output
|
141
|
+
# EasyAudio::EasyStream.new(in: true, out: true) { current_sample }.start
|
142
|
+
# @example Play a sine wave.
|
143
|
+
# EasyAudio::EasyStream.new(&EasyAudio::Waveforms::SINE).start
|
144
|
+
# @example Play a square wave.
|
145
|
+
# EasyAudio::EasyStream.new(&EasyAudio::Waveforms::SQUARE).start
|
146
|
+
def initialize(opts = {}, &block)
|
147
|
+
@frequency = opts[:freq] || 440.0
|
148
|
+
@amp = opts[:amp] || 1.0
|
149
|
+
@frame = 0
|
150
|
+
@channel = 0
|
151
|
+
|
152
|
+
super(opts, &block)
|
153
|
+
end
|
154
|
+
|
155
|
+
attr_accessor :amp, :frequency, :frame
|
156
|
+
attr_reader :step, :channel, :samples, :num_frames
|
157
|
+
attr_reader :time_info, :status_info, :user_data, :i, :current_sample
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def run_process(input, output, frames, time_info, status, user_data)
|
162
|
+
@samples = nil
|
163
|
+
if input.address != 0
|
164
|
+
@samples = input.read_array_of_float(frames * @input_channels)
|
165
|
+
end
|
166
|
+
|
167
|
+
@current_sample = nil
|
168
|
+
@num_frames = frames
|
169
|
+
@time_info = time_info
|
170
|
+
@status_info = status
|
171
|
+
@user_data = user_data
|
172
|
+
|
173
|
+
result = Array.new(frames * @output_channels)
|
174
|
+
if @fn
|
175
|
+
@i = 0
|
176
|
+
frames.times do
|
177
|
+
@step = @frame * (@frequency / @sample_rate.to_f) % 1.0
|
178
|
+
@output_channels.times do |ch|
|
179
|
+
@channel = ch
|
180
|
+
@current_sample = @samples[@i] if @samples
|
181
|
+
result[@i] = @amp.to_f * (instance_exec(&@fn) || 0.0)
|
182
|
+
@i += 1
|
183
|
+
end
|
184
|
+
@frame = (@frame + 1) % 1000000
|
185
|
+
end
|
186
|
+
else
|
187
|
+
result = result.map {0}
|
188
|
+
end
|
189
|
+
|
190
|
+
result
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
module_function
|
195
|
+
|
196
|
+
# Quickly opens a {Stream} and calls {Stream#start}.
|
197
|
+
#
|
198
|
+
# @option (see Stream#initialize)
|
199
|
+
# @yield (see Stream#initialize)
|
200
|
+
# @yieldparam (see Stream#initialize)
|
201
|
+
# @yieldreturn (see Stream#initialize)
|
202
|
+
def open(opts = {}, &block)
|
203
|
+
Stream.new(opts, &block).tap {|s| s.start }
|
204
|
+
end
|
205
|
+
|
206
|
+
# Quickly opens an {EasyStream} and calls {Stream#start}.
|
207
|
+
#
|
208
|
+
# @option (see EasyStream#initialize)
|
209
|
+
# @yield (see EasyStream#initialize)
|
210
|
+
# @yieldreturn (see EasyStream#initialize)
|
211
|
+
# @example Process audio from input (microphone) and playback on output
|
212
|
+
# EasyAudio.easy_open(in: true, out: true) { current_sample }
|
213
|
+
# @example Play a sine wave.
|
214
|
+
# EasyAudio.easy_open(&EasyAudio::Waveforms::SINE)
|
215
|
+
# @example Play a square wave.
|
216
|
+
# EasyAudio.easy_open(&EasyAudio::Waveforms::SQUARE)
|
217
|
+
# @see EasyStream#initialize
|
218
|
+
def easy_open(opts = {}, &block)
|
219
|
+
EasyStream.new(opts, &block).tap {|s| s.start }
|
220
|
+
end
|
221
|
+
|
222
|
+
# A collection of pre-fabricated waveforms that can be plugged into
|
223
|
+
# {EasyStream} or {easy_open}.
|
224
|
+
module Waveforms
|
225
|
+
# Generates a sine wave
|
226
|
+
SINE = -> { Math.sin(2 * Math::PI * step) }
|
227
|
+
|
228
|
+
# Generates a square wave
|
229
|
+
SQUARE = -> { step < 0.5 ? -1 : 1 }
|
230
|
+
|
231
|
+
# Generates a triangle wave
|
232
|
+
TRIANGLE = -> { 1 - 4 * (step.round - step).abs }
|
233
|
+
|
234
|
+
# Generates a sawtooth wave
|
235
|
+
SAW = -> { 2 * (step - step.round) }
|
236
|
+
end
|
237
|
+
end
|
data/samus.json
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
{
|
2
|
+
"actions": [
|
3
|
+
{
|
4
|
+
"action": "fs-sedfiles",
|
5
|
+
"files": ["lib/easy_audio.rb"],
|
6
|
+
"arguments": {
|
7
|
+
"search": "VERSION = ['\"](.+?)['\"]",
|
8
|
+
"replace": "VERSION = \"$version\""
|
9
|
+
}
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"action": "git-commit",
|
13
|
+
"files": ["lib/easy_audio.rb"]
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"action": "git-merge",
|
17
|
+
"arguments": {
|
18
|
+
"branch": "master"
|
19
|
+
}
|
20
|
+
},
|
21
|
+
{
|
22
|
+
"action": "archive-git-full",
|
23
|
+
"files": ["git.tgz"],
|
24
|
+
"publish": [{
|
25
|
+
"action": "git-push",
|
26
|
+
"arguments": {
|
27
|
+
"remotes": "origin",
|
28
|
+
"refs": "master v$version"
|
29
|
+
}
|
30
|
+
}]
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"action": "gem-build",
|
34
|
+
"files": ["*.gemspec"],
|
35
|
+
"publish": [
|
36
|
+
{
|
37
|
+
"action": "gem-push",
|
38
|
+
"files": ["*.gem"],
|
39
|
+
"credentials": "lsegal.rubygems"
|
40
|
+
}
|
41
|
+
]
|
42
|
+
}
|
43
|
+
]
|
44
|
+
}
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: easy_audio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Loren Segal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi-portaudio
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.0'
|
27
|
+
description: EasyAudio allows you to play or record from your sound card.
|
28
|
+
email: lsegal@soen.ca
|
29
|
+
executables: []
|
30
|
+
extensions:
|
31
|
+
- Rakefile
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- easy_audio.gemspec
|
39
|
+
- examples/increase_frequency.rb
|
40
|
+
- examples/one_second_sine.rb
|
41
|
+
- examples/record_microphone_delay.rb
|
42
|
+
- lib/easy_audio.rb
|
43
|
+
- samus.json
|
44
|
+
homepage: http://github.com/lsegal/easy_audio
|
45
|
+
licenses:
|
46
|
+
- BSD
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.2.2
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: EasyAudio is a simplified wrapper for the portaudio library.
|
68
|
+
test_files: []
|
69
|
+
has_rdoc:
|