feep 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e59eb850a3b66b00df0a1f7e42523e7f1d7f6974
4
+ data.tar.gz: e032678907f285574b847199f530cd66a8eaa734
5
+ SHA512:
6
+ metadata.gz: 69e83b10a38ed0b4a7a3378fe874fc5054b57a4bb8ec38ec02eec736c4fb8a36e3958d2e6973a092f141e32b9300857b7e92f402a3c085a37f2308402c9f5de2
7
+ data.tar.gz: 545f7debf3dc9801a85a27fdba7f2531d1a682b78a22cf681add3674eda27a80dd3207dabc3c978c4fa4cf716d44e2284ca4cfecde8dd0b72c3ede03c125bcda
@@ -0,0 +1,4 @@
1
+ .idea/*
2
+ pkg/*
3
+ *.gem
4
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,60 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ feep (0.0.1)
5
+ os (~> 0.9, >= 0.9.6)
6
+ wavefile (= 0.6.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ byebug (3.5.1)
12
+ columnize (~> 0.8)
13
+ debugger-linecache (~> 1.2)
14
+ slop (~> 3.6)
15
+ coderay (1.1.0)
16
+ columnize (0.9.0)
17
+ debugger-linecache (1.2.0)
18
+ diff-lcs (1.2.5)
19
+ method_source (0.8.2)
20
+ os (0.9.6)
21
+ pry (0.10.1)
22
+ coderay (~> 1.1.0)
23
+ method_source (~> 0.8.1)
24
+ slop (~> 3.4)
25
+ pry (0.10.1-x64-mingw32)
26
+ coderay (~> 1.1.0)
27
+ method_source (~> 0.8.1)
28
+ slop (~> 3.4)
29
+ win32console (~> 1.3)
30
+ pry-byebug (3.0.1)
31
+ byebug (~> 3.4)
32
+ pry (~> 0.10)
33
+ rake (10.4.2)
34
+ rspec (3.2.0)
35
+ rspec-core (~> 3.2.0)
36
+ rspec-expectations (~> 3.2.0)
37
+ rspec-mocks (~> 3.2.0)
38
+ rspec-core (3.2.1)
39
+ rspec-support (~> 3.2.0)
40
+ rspec-expectations (3.2.0)
41
+ diff-lcs (>= 1.2.0, < 2.0)
42
+ rspec-support (~> 3.2.0)
43
+ rspec-mocks (3.2.1)
44
+ diff-lcs (>= 1.2.0, < 2.0)
45
+ rspec-support (~> 3.2.0)
46
+ rspec-support (3.2.2)
47
+ slop (3.6.0)
48
+ wavefile (0.6.0)
49
+ win32console (1.3.2)
50
+
51
+ PLATFORMS
52
+ ruby
53
+ x64-mingw32
54
+
55
+ DEPENDENCIES
56
+ bundler (~> 1.8)
57
+ feep!
58
+ pry-byebug (~> 3.0)
59
+ rake (~> 10.0)
60
+ rspec (>= 3.0)
@@ -0,0 +1,38 @@
1
+ # Feep
2
+
3
+ ## Wha?
4
+ Use the power of Ruby gems to make your computer [feep](http://dictionary.reference.com/browse/feep) (except more musically) using sweet [WAV-file-writing technology](http://wavefilegem.com) from [Joel Strait](https://github.com/jstrait). Works on both Windows and *nix (including OS X) as it uses the standard WAV format to do its bidding.
5
+
6
+ _Note:_ In order for the sound-playing magic to work on Windows, you will need [sounder](http://www.elifulkerson.com/projects/commandline-wav-player.php), a free command-line WAV file player on your system and in your path. Mac and *nix uses `afplay`, which should be built-in, but feel free to change either to something you already have or desire to install.
7
+
8
+ ## Why?
9
+
10
+ Besides a quick way to make some kind of noise, which I always appreciate, this could be used to tie into another Ruby script for an alert tone or maybe even some wicked cool command-line game that needs musical note sound effects. The opportunities are essentially endless.
11
+
12
+ ## How?
13
+
14
+ For now:
15
+ 1. `git clone git@github.com:michaelchadwick/feep`
16
+ 2. `cd feep`
17
+ 3. `gem build feep.gemspec`
18
+ 4. `gem install feep-0.0.1.gem`
19
+ 5. `bundle install`
20
+ 6. `feep`
21
+
22
+ Feep doesn't require any parameters, as it will play a 440Hz/A4 sine wave at 50% full volume for 1000 milliseconds unless you supply one of the below options. Feep will only save the resulting WAV file it creates if you specify the `-save` parameter.
23
+
24
+ The full usage looks like this:
25
+
26
+ `feep [-fn frequency|note_name|comma-delimited_frequencies_or_note_names] [-w waveform] [-v volume] [-d duration] [-save] [-loud]`
27
+
28
+ `-frequency|note_name|commad-delimted_frequences_or_note_names`: a number from 0 to 20000. You can try something bigger or smaller, but you may get odd results. You may also enter any note name from C0 to B9 (or even flats and sharps like C#6 or Eb5). You may also also enter some combination of these with commas between them and it'll play all of them together in a chord.
29
+
30
+ `-waveform`: a string equal to "sine", "square", "saw", "triangle", or "noise".
31
+
32
+ `-volume`: a number from 0.0 (silence (why would you do this?)) to 1.0 (blast it)
33
+
34
+ `-duration`: number of milliseconds for the sound to last
35
+
36
+ `-save`: save the resulting WAV file in the current directory. Will create it in the format of `waveform_frequency-in-Hz_volume_duration.wav`
37
+
38
+ `-loud`: displays note and file-making information
@@ -0,0 +1,3 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'feep'
5
+
6
+ USAGE_INSTRUCTIONS = ''
7
+
8
+ def parse_options
9
+ options = {:freq_or_note => '440.000', :waveform => 'sine', :volume => 0.5, :duration => 1000, :save => false, :loud => false}
10
+
11
+ optparse = OptionParser.new do |opts|
12
+ opts.banner = 'usage: feep [frequency|note_name|list_of_frequencies_or_note_names] [waveform] [volume] [duration] [save] [-loud]'
13
+
14
+ opts.on('-f', '-n', '--freq-or-note FREQUENCY|NOTE_NAME', 'One or more frequencies or note names to play at once, e.g. 440 or A4 or 220,440,880') do |f_or_n|
15
+ options[:freq_or_note] = f_or_n
16
+ end
17
+
18
+ opts.on('-w', '--wave WAVE_FORM_NAME', 'Waveform type to use for the sound') do |w|
19
+ options[:waveform] = w
20
+ end
21
+
22
+ opts.on('-a', '--amplitude MAX_AMPLITUDE', 'Amplitude/volume (0.0 - 1.0) to play the sound(s) at') do |a|
23
+ options[:volume] = a.to_f
24
+ end
25
+
26
+ opts.on('-d', '--duration DURATION', 'Duration in ms to play the sound(s)') do |d|
27
+ options[:duration] = d.to_i
28
+ end
29
+
30
+ opts.on('-s', '--save', 'Save the resulting WAV file in the current directory') do
31
+ options[:save] = true
32
+ end
33
+
34
+ opts.on('-l', '--loud', 'Displays information about note(s) being played') do
35
+ options[:loud] = true
36
+ end
37
+
38
+ opts.on('-v', '--version', 'Display version number and exit') do
39
+ puts "#{$0} #{Feep::VERSION}"
40
+ exit
41
+ end
42
+
43
+ opts.on( '-h', '--help', 'Display this screen and exit') do
44
+ puts opts
45
+ exit
46
+ end
47
+ end
48
+
49
+ USAGE_INSTRUCTIONS << optparse.to_s
50
+ optparse.parse!()
51
+
52
+ return options
53
+ end
54
+
55
+ def print_error(error)
56
+ case error
57
+ when OptionParser::InvalidOption
58
+ puts "feep: illegal option #{error.args.join(' ')}"
59
+ puts USAGE_INSTRUCTIONS
60
+ else
61
+ puts 'An unexpected error occurred while running Feep:'
62
+ puts " #{error}\n"
63
+ end
64
+ end
65
+
66
+ begin
67
+ options = parse_options()
68
+
69
+ Feep.new(options)
70
+ rescue => error
71
+ print_error(error)
72
+ exit(false)
73
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "feep/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'feep'
8
+ spec.version = Feep::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.authors = ["Michael Chadwick"]
11
+ spec.email = 'mike@codana.me'
12
+ spec.homepage = "http://rubygemspec.org/gems/feep"
13
+ spec.summary = %q{Make your computer feep with Ruby}
14
+ spec.description = %q{Use Ruby to make your computer beep at a certain frequency for a certain duration. Do it for fun, or add it to other programs for easy alert sounds.}
15
+
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+ spec.license = 'MIT'
21
+
22
+ spec.add_runtime_dependency 'wavefile', '= 0.6.0'
23
+ spec.add_runtime_dependency 'os', '~> 0.9', '>= 0.9.6'
24
+
25
+ spec.add_development_dependency 'pry-byebug', '~> 3.0'
26
+ spec.add_development_dependency 'bundler', '~> 1.8'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec', '>= 3.0'
29
+ end
@@ -0,0 +1,213 @@
1
+ require 'wavefile'
2
+ require 'os'
3
+ require 'feep/constants'
4
+
5
+ class Feep
6
+
7
+ # main entry point
8
+ def initialize(options)
9
+ @options = options
10
+ configure_sound(options)
11
+ end
12
+
13
+ # convert midi notes to frequencies
14
+ def midi_to_freq(midi_note)
15
+ return 440.0 * (2.0 ** ((midi_note.to_f-69)/12))
16
+ end
17
+
18
+ # convert frequencies to midi notes
19
+ def freq_to_midi(freq)
20
+ return (69 + 12 * (Math.log2(freq.to_i.abs / 440.0))).round
21
+ end
22
+
23
+ # makes sure that whatever kind of sound was entered on the CLI
24
+ # it is now a frequency to feed into the sample data generator
25
+ def convert_note_to_freq(freq_or_note)
26
+ if freq_or_note.match(/[A-Za-z]/)
27
+ if NOTE_FREQ.has_key?(freq_or_note)
28
+ frequency = NOTE_FREQ[freq_or_note]
29
+ else
30
+ app_error(ERROR_MSG[:note_name])
31
+ end
32
+ else
33
+ frequency = freq_or_note
34
+ end
35
+
36
+ return frequency
37
+ end
38
+
39
+ # takes CLI options, massages them, and passes them to the
40
+ # sound generation methods
41
+ def configure_sound(options)
42
+ ### A. Check non-essential options
43
+ if !WAVE_TYPES.include?(options[:waveform])
44
+ app_error(ERROR_MSG[:wave_form])
45
+ end
46
+
47
+ # Convert ms to secs in order to multiply the sample rate by
48
+ duration_s = (options[:duration].to_f / 1000)
49
+
50
+ # Make the samples to write a nice integer
51
+ samples_to_write = (SAMPLE_RATE * duration_s).to_i
52
+
53
+ ### B. Set frequency/note, or group of frequencies/notes, to play
54
+
55
+ # Is it a chord or a note?
56
+ if options[:freq_or_note].include?(',')
57
+ # yes, it's a chord, so create threads
58
+ threads = []
59
+ options[:freq_or_note].split(',').each do |note|
60
+ sound_to_play = convert_note_to_freq(note)
61
+ output_filename = "#{options[:waveform]}_#{sound_to_play}Hz_#{options[:volume].to_f}_#{options[:duration].to_s}.wav"
62
+ threads << Thread.new {
63
+ play_note(sound_to_play.to_f, options[:waveform], options[:volume].to_f, options[:duration].to_i, samples_to_write, output_filename)
64
+ }
65
+ end
66
+ threads.each { |th| th.join }
67
+ else
68
+ # no, it's a single note
69
+ sound_to_play = convert_note_to_freq(options[:freq_or_note])
70
+ output_filename = "#{options[:waveform]}_#{sound_to_play}Hz_#{options[:volume].to_f}_#{options[:duration].to_s}.wav"
71
+ play_note(sound_to_play, options[:waveform], options[:volume].to_f, options[:duration].to_i, samples_to_write, output_filename)
72
+ end
73
+ end
74
+
75
+ # plays note using system wav file player
76
+ def play_sound(file, duration)
77
+ delimiter = OS.windows? ? ';' : ':'
78
+
79
+ system_apps = ENV['PATH'].split(delimiter).collect {|d| Dir.entries d if Dir.exists? d}.flatten
80
+
81
+ if OS.windows?
82
+ if system_apps.include? SNDPLAYER_WIN
83
+ display_text_beep(duration)
84
+ system("#{SNDPLAYER_WIN} #{file}")
85
+ else
86
+ puts "couldn't find #{SNDPLAYER_WIN}"
87
+ end
88
+ end
89
+
90
+ if OS.mac? || OS.linux?
91
+ if system_apps.include? SNDPLAYER_UNIX
92
+ display_text_beep(duration)
93
+ system("#{SNDPLAYER_UNIX} #{file}")
94
+ else
95
+ puts "couldn't find #{SNDPLAYER_UNIX}"
96
+ end
97
+ end
98
+ end
99
+
100
+ # displays a fun beep message
101
+ def display_text_beep(duration)
102
+ print 'Be'
103
+ 1.upto(duration) {|ms|
104
+ if ms % 100 == 0
105
+ print 'e'
106
+ end
107
+ }
108
+ puts 'ep!'
109
+ end
110
+
111
+ # removes the sound, unless marked to save
112
+ def remove_sound(file)
113
+ if !@options[:save]
114
+ if OS.windows?
115
+ system("del #{file}")
116
+ else
117
+ system("rm #{file}")
118
+ end
119
+ else
120
+ if @options[:loud]
121
+ info = WaveFile::Reader.info(file)
122
+ duration = info.duration
123
+ formatted_duration = duration.minutes.to_s.rjust(2, '0') << ':' <<
124
+ duration.seconds.to_s.rjust(2, '0') << ':' <<
125
+ duration.milliseconds.to_s.rjust(3, '0')
126
+ puts ""
127
+ puts "Created #{file}"
128
+ puts "---"
129
+ puts "Length: #{formatted_duration}"
130
+ puts "Format: #{info.audio_format}"
131
+ puts "Channels: #{info.channels}"
132
+ puts "Frames: #{info.sample_frame_count}"
133
+ puts "Sample Rate: #{info.sample_rate}"
134
+ end
135
+ end
136
+ end
137
+
138
+ # code from Joel Strait's nanosynth to generate raw audio
139
+ def create_sound(frequency, waveform, samples, volume, output_filename)
140
+ # Generate sample data for the given frequency, amplitude, and duration.
141
+ # Since we are using a sample rate of 44,100Hz, 44,100 samples are required for one second of sound.
142
+ samples = generate_sample_data(waveform.to_sym, samples, frequency.to_f, volume.to_f)
143
+
144
+ # Wrap the array of samples in a Buffer, so that it can be written to a Wave file
145
+ # by the WaveFile gem. Since we generated samples between -1.0 and 1.0, the sample
146
+ # type should be :float
147
+ buffer = WaveFile::Buffer.new(samples, WaveFile::Format.new(:mono, :float, 44100))
148
+
149
+ # Write the Buffer containing our samples to a 16-bit, monophonic Wave file
150
+ # with a sample rate of 44,100Hz, using the WaveFile gem.
151
+ WaveFile::Writer.new(output_filename, WaveFile::Format.new(:mono, :pcm_16, 44100)) do |writer|
152
+ writer.write(buffer)
153
+ end
154
+ end
155
+
156
+ # more code from Joel Strait's nanosynth (http://joe)
157
+ # The dark heart of NanoSynth, the part that actually generates the audio data
158
+ def generate_sample_data(wave_type, num_samples, frequency, max_amplitude)
159
+ position_in_period = 0.0
160
+ position_in_period_delta = frequency / SAMPLE_RATE
161
+
162
+ # Initialize an array of samples set to 0.0. Each sample will be replaced with
163
+ # an actual value below.
164
+ samples = [].fill(0.0, 0, num_samples)
165
+
166
+ num_samples.times do |i|
167
+ # Add next sample to sample list. The sample value is determined by
168
+ # plugging position_in_period into the appropriate wave function.
169
+ if wave_type == :sine
170
+ samples[i] = Math::sin(position_in_period * TWO_PI) * max_amplitude
171
+ elsif wave_type == :square
172
+ samples[i] = (position_in_period >= 0.5) ? max_amplitude : -max_amplitude
173
+ elsif wave_type == :saw
174
+ samples[i] = ((position_in_period * 2.0) - 1.0) * max_amplitude
175
+ elsif wave_type == :triangle
176
+ samples[i] = max_amplitude - (((position_in_period * 2.0) - 1.0) * max_amplitude * 2.0).abs
177
+ elsif wave_type == :noise
178
+ samples[i] = RANDOM_GENERATOR.rand(-max_amplitude..max_amplitude)
179
+ end
180
+
181
+ position_in_period += position_in_period_delta
182
+
183
+ # Constrain the period between 0.0 and 1.0.
184
+ # That is, keep looping and re-looping over the same period.
185
+ if(position_in_period >= 1.0)
186
+ position_in_period -= 1.0
187
+ end
188
+ end
189
+
190
+ return samples
191
+ end
192
+
193
+ # creates, plays, and removes note
194
+ def play_note(frequency, waveform, volume, duration, samples_to_write, output_filename)
195
+ if @options[:loud]
196
+ puts 'Playing note'
197
+ puts " frequency: #{frequency.to_f.abs}"
198
+ puts " midi: #{freq_to_midi(frequency)}"
199
+ puts " duration: #{duration}"
200
+ end
201
+ create_sound(frequency, waveform, samples_to_write, volume, output_filename)
202
+ play_sound(output_filename, duration)
203
+ remove_sound(output_filename)
204
+ end
205
+
206
+ # displays error, usage, and exits
207
+ def app_error(msg)
208
+ puts "#{File.basename($0).split(".")[0]}: #{msg}"
209
+ puts 'usage: feep [frequency|note_name|list_of_frequencies_or_note_names] [sine|square|saw|triangle|noise] [volume] [duration] [save]'
210
+ exit
211
+ end
212
+
213
+ end
@@ -0,0 +1,186 @@
1
+ class Feep
2
+ SNDPLAYER_WIN = 'sounder.exe'
3
+ SNDPLAYER_UNIX = 'afplay'
4
+ SAMPLE_RATE = 44100
5
+ TWO_PI = 2 * Math::PI
6
+ RANDOM_GENERATOR = Random.new
7
+ WAVE_TYPES = %w[sine square saw triangle noise]
8
+
9
+ NOTE_FREQ = Hash[
10
+ 'C0' => 16.351,
11
+ 'C#0' => 17.324,
12
+ 'Db0' => 17.324,
13
+ 'D0' => 18.354,
14
+ 'D#0' => 19.445,
15
+ 'Eb0' => 19.445,
16
+ 'E0' => 20.601,
17
+ 'F0' => 21.827,
18
+ 'F#0' => 23.124,
19
+ 'Gb0' => 23.124,
20
+ 'G0' => 24.499,
21
+ 'G#0' => 25.956,
22
+ 'Ab0' => 25.956,
23
+ 'A0' => 27.500,
24
+ 'A#0' => 29.135,
25
+ 'Bb0' => 29.135,
26
+ 'B0' => 30.868,
27
+ 'C1' => 32.703,
28
+ 'C#1' => 34.648,
29
+ 'Db1' => 34.648,
30
+ 'D1' => 36.708,
31
+ 'D#1' => 38.891,
32
+ 'Eb1' => 38.891,
33
+ 'E1' => 41.203,
34
+ 'F1' => 43.654,
35
+ 'F#1' => 46.249,
36
+ 'Gb1' => 46.249,
37
+ 'G1' => 48.999,
38
+ 'G#1' => 51.913,
39
+ 'Ab1' => 51.913,
40
+ 'A1' => 55.000,
41
+ 'A#1' => 58.270,
42
+ 'Bb1' => 58.270,
43
+ 'B1' => 61.375,
44
+ 'C2' => 65.406,
45
+ 'C#2' => 69.296,
46
+ 'Db2' => 69.296,
47
+ 'D2' => 73.416,
48
+ 'D#2' => 77.782,
49
+ 'Eb2' => 77.782,
50
+ 'E2' => 82.407,
51
+ 'F2' => 87.307,
52
+ 'F#2' => 92.499,
53
+ 'Gb2' => 92.499,
54
+ 'G2' => 97.999,
55
+ 'G#2' => 97.999,
56
+ 'Ab2' => 103.826,
57
+ 'A2' => 110.000,
58
+ 'A#2' => 116.541,
59
+ 'Bb2' => 116.541,
60
+ 'B2' => 123.471,
61
+ 'C3' => 130.813,
62
+ 'C#3' => 138.591,
63
+ 'Db3' => 138.591,
64
+ 'D3' => 146.832,
65
+ 'D#3' => 155.564,
66
+ 'Eb3' => 155.564,
67
+ 'E3' => 164.814,
68
+ 'F3' => 174.614,
69
+ 'F#3' => 184.997,
70
+ 'Gb3' => 184.997,
71
+ 'G3' => 195.998,
72
+ 'G#3' => 207.652,
73
+ 'Ab3' => 207.652,
74
+ 'A3' => 220.000,
75
+ 'A#3' => 233.082,
76
+ 'Bb3' => 233.082,
77
+ 'B3' => 246.942,
78
+ 'C4' => 261.626,
79
+ 'C#4' => 277.183,
80
+ 'Db4' => 277.183,
81
+ 'D4' => 293.665,
82
+ 'D#4' => 311.127,
83
+ 'Eb4' => 311.127,
84
+ 'E4' => 329.628,
85
+ 'F4' => 349.228,
86
+ 'F#4' => 369.994,
87
+ 'Gb4' => 369.994,
88
+ 'G4' => 391.995,
89
+ 'G#4' => 415.305,
90
+ 'Ab4' => 415.305,
91
+ 'A4' => 440.000,
92
+ 'A#4' => 466.164,
93
+ 'Bb4' => 466.164,
94
+ 'B4' => 493.883,
95
+ 'C5' => 523.251,
96
+ 'C#5' => 554.365,
97
+ 'Db5' => 554.365,
98
+ 'D5' => 587.330,
99
+ 'D#5' => 622.254,
100
+ 'Eb5' => 622.254,
101
+ 'E5' => 659.255,
102
+ 'F5' => 698.457,
103
+ 'F#5' => 739.989,
104
+ 'Gb5' => 739.989,
105
+ 'G5' => 783.991,
106
+ 'G#5' => 830.609,
107
+ 'Ab5' => 830.609,
108
+ 'A5' => 880.000,
109
+ 'A#5' => 932.328,
110
+ 'Bb5' => 932.328,
111
+ 'B5' => 987.767,
112
+ 'C6' => 1046.502,
113
+ 'C#6' => 1108.731,
114
+ 'Db6' => 1108.731,
115
+ 'D6' => 1174.659,
116
+ 'D#6' => 1244.508,
117
+ 'Eb6' => 1244.508,
118
+ 'E6' => 1318.510,
119
+ 'F6' => 1396.913,
120
+ 'F#6' => 1479.978,
121
+ 'Gb6' => 1479.978,
122
+ 'G6' => 1567.982,
123
+ 'G#6' => 1661.219,
124
+ 'Ab6' => 1661.219,
125
+ 'A6' => 1760.000,
126
+ 'A#6' => 1864.655,
127
+ 'Bb6' => 1864.655,
128
+ 'B6' => 1975.533,
129
+ 'C7' => 2093.005,
130
+ 'C#7' => 2217.461,
131
+ 'Db7' => 2217.461,
132
+ 'D7' => 2349.318,
133
+ 'D#7' => 2489.016,
134
+ 'Eb7' => 2489.016,
135
+ 'E7' => 2637.021,
136
+ 'F7' => 2793.826,
137
+ 'F#7' => 2959.956,
138
+ 'Gb7' => 2959.956,
139
+ 'G7' => 3135.964,
140
+ 'G#7' => 3322.438,
141
+ 'Ab7' => 3322.438,
142
+ 'A7' => 3520.000,
143
+ 'A#7' => 3729.310,
144
+ 'Bb7' => 3729.310,
145
+ 'B7' => 3951.066,
146
+ 'C8' => 4186.009,
147
+ 'C#8' => 4434.922,
148
+ 'Db8' => 4434.922,
149
+ 'D8' => 4698.636,
150
+ 'D#8' => 4978.032,
151
+ 'Eb8' => 4978.032,
152
+ 'E8' => 5274.042,
153
+ 'F8' => 5587.652,
154
+ 'F#8' => 5919.910,
155
+ 'Gb8' => 5919.910,
156
+ 'G8' => 6271.928,
157
+ 'G#8' => 6644.876,
158
+ 'Ab8' => 6644.876,
159
+ 'A8' => 7040.000,
160
+ 'A#8' => 7458.620,
161
+ 'Bb8' => 7458.620,
162
+ 'B8' => 7902.132,
163
+ 'C9' => 8372.018,
164
+ 'C#9' => 8869.844,
165
+ 'Db9' => 8869.844,
166
+ 'D9' => 9397.272,
167
+ 'D#9' => 9956.064,
168
+ 'Eb9' => 9956.064,
169
+ 'E9' => 10548.084,
170
+ 'F9' => 11175.304,
171
+ 'F#9' => 11839.820,
172
+ 'Gb9' => 11839.820,
173
+ 'G9' => 12543.856,
174
+ 'G#9' => 13289.752,
175
+ 'Ab9' => 13289.752,
176
+ 'A9' => 14080.000,
177
+ 'A#9' => 14917.240,
178
+ 'Bb9' => 14917.240,
179
+ 'B9' => 15804.264
180
+ ]
181
+
182
+ ERROR_MSG = Hash[
183
+ :note_name => 'Note name argument is invalid.',
184
+ :wave_form => 'Wave form type is invalid.'
185
+ ]
186
+ end
@@ -0,0 +1,3 @@
1
+ class Feep
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Feep do
4
+ subject { Feep.new }
5
+
6
+ describe '#play_sound' do
7
+ options = {
8
+ :freq_or_note => '440.000',
9
+ :waveform => 'sine',
10
+ :volume => 0.5,
11
+ :duration => 500,
12
+ :save => false,
13
+ :loud => false
14
+ }
15
+
16
+ it 'plays a sound with no options' do
17
+ expect(Feep.new(options)).to eq "sound played"
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1 @@
1
+ require 'feep'
@@ -0,0 +1,3 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: feep
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Chadwick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: wavefile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.6.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.6.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: os
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.9.6
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '0.9'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.9.6
47
+ - !ruby/object:Gem::Dependency
48
+ name: pry-byebug
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.8'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.8'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '10.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '10.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '3.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '3.0'
103
+ description: Use Ruby to make your computer beep at a certain frequency for a certain
104
+ duration. Do it for fun, or add it to other programs for easy alert sounds.
105
+ email: mike@codana.me
106
+ executables:
107
+ - feep
108
+ extensions: []
109
+ extra_rdoc_files: []
110
+ files:
111
+ - ".gitignore"
112
+ - Gemfile
113
+ - Gemfile.lock
114
+ - README.md
115
+ - Rakefile
116
+ - bin/feep
117
+ - feep.gemspec
118
+ - lib/feep.rb
119
+ - lib/feep/constants.rb
120
+ - lib/feep/version.rb
121
+ - spec/feep_spec.rb
122
+ - spec/spec_helper.rb
123
+ - tasks/rspec.rake
124
+ homepage: http://rubygemspec.org/gems/feep
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.4.5
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Make your computer feep with Ruby
148
+ test_files: []
149
+ has_rdoc: