cw 0.2.4 → 0.3.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.cw_config +18 -0
  3. data/.gitignore +10 -1
  4. data/LICENSE +2 -1
  5. data/README.md +212 -96
  6. data/Rakefile +15 -2
  7. data/VERSION +1 -1
  8. data/Vagrantfile +45 -0
  9. data/cw.gemspec +6 -1
  10. data/data/text/book_to_read.txt +4 -0
  11. data/data/text/english.txt +10000 -0
  12. data/example.rb +172 -106
  13. data/lib/cw.rb +10 -126
  14. data/lib/cw/alphabet.rb +53 -46
  15. data/lib/cw/audio_player.rb +83 -72
  16. data/lib/cw/book.rb +160 -185
  17. data/lib/cw/book_details.rb +38 -49
  18. data/lib/cw/cl.rb +101 -95
  19. data/lib/cw/common_words.rb +76 -0
  20. data/lib/cw/config.rb +50 -0
  21. data/lib/cw/current_word.rb +23 -24
  22. data/lib/cw/cw_dsl.rb +264 -131
  23. data/lib/cw/cw_encoding.rb +63 -69
  24. data/lib/cw/cw_stream.rb +86 -82
  25. data/lib/cw/cw_threads.rb +132 -22
  26. data/lib/cw/element.rb +60 -54
  27. data/lib/cw/file_details.rb +26 -11
  28. data/lib/cw/key_input.rb +53 -35
  29. data/lib/cw/numbers.rb +26 -19
  30. data/lib/cw/os.rb +13 -0
  31. data/lib/cw/play.rb +92 -0
  32. data/lib/cw/print.rb +102 -100
  33. data/lib/cw/process.rb +3 -0
  34. data/lib/cw/progress.rb +20 -17
  35. data/lib/cw/randomize.rb +56 -52
  36. data/lib/cw/repeat_word.rb +59 -66
  37. data/lib/cw/reveal.rb +32 -31
  38. data/lib/cw/rss.rb +52 -48
  39. data/lib/cw/sentence.rb +83 -76
  40. data/lib/cw/speak.rb +8 -4
  41. data/lib/cw/spoken.rb +8 -4
  42. data/lib/cw/str.rb +62 -30
  43. data/lib/cw/test_letters.rb +20 -28
  44. data/lib/cw/test_words.rb +25 -31
  45. data/lib/cw/tester.rb +219 -226
  46. data/lib/cw/text_helpers.rb +19 -15
  47. data/lib/cw/timing.rb +63 -67
  48. data/lib/cw/tone_generator.rb +176 -153
  49. data/lib/cw/tone_helpers.rb +15 -23
  50. data/lib/cw/voice.rb +12 -8
  51. data/lib/cw/words.rb +136 -106
  52. data/run_script_tests.rb +165 -0
  53. data/test/my_words.txt +1 -0
  54. data/test/test_common_words.rb +71 -0
  55. data/test/test_config.rb +98 -0
  56. data/test/test_current_word.rb +62 -0
  57. data/test/test_cw.rb +87 -120
  58. data/test/test_cw_threads.rb +123 -0
  59. data/test/test_filtering.rb +439 -0
  60. data/test/test_params.rb +28 -0
  61. data/test/test_play.rb +51 -0
  62. data/test/test_stream.rb +83 -83
  63. data/test/test_tester.rb +9 -27
  64. data/test/test_timing.rb +212 -0
  65. metadata +94 -12
  66. data/lib/cw/config_file.rb +0 -69
  67. data/lib/cw/monitor_keys.rb +0 -37
  68. data/lib/cw/params.rb +0 -104
@@ -1,25 +1,29 @@
1
1
  # encoding: utf-8
2
2
 
3
- module TextHelpers
3
+ module CWG
4
4
 
5
- def letter_group
6
- (97..122).to_a
7
- end
5
+ module TextHelpers
8
6
 
9
- def number_group
10
- (48..57).to_a
11
- end
7
+ def letter_group
8
+ (97..122).to_a
9
+ end
12
10
 
13
- def cw_chars chr
14
- chr.tr('^a-z0-9\.\,+', '')
15
- end
11
+ def number_group
12
+ (48..57).to_a
13
+ end
14
+
15
+ def cw_chars chr
16
+ chr.tr('^a-z0-9\.\,+', '')
17
+ end
16
18
 
17
- def exclude_non_cw_chars word
18
- temp = ''
19
- word.split.each do |chr|
20
- temp += chr if letter(chr)
19
+ def exclude_non_cw_chars word
20
+ temp = ''
21
+ word.split.each do |chr|
22
+ temp += chr if letter(chr)
23
+ end
24
+ temp
21
25
  end
22
- temp
26
+
23
27
  end
24
28
 
25
29
  end
@@ -1,92 +1,88 @@
1
1
  # encoding: utf-8
2
2
 
3
- class Timing
3
+ module CWG
4
4
 
5
- attr_accessor :delay_time
6
- attr_accessor :start_time
5
+ class Timing
7
6
 
8
- def initialize
9
- @delay_time = 0.0
10
- @cw_encoding = CwEncoding.new
11
- end
12
-
13
- def cw_encoding enc
14
- @cw_encoding.fetch(enc)
15
- end
7
+ attr_accessor :delay_time
8
+ attr_accessor :start_time
16
9
 
17
- def dot wpm
18
- 1.2 / wpm.to_f
19
- end
10
+ def initialize
11
+ @delay_time = 0.0
12
+ @cw_encoding = CwEncoding.new
13
+ end
20
14
 
21
- def dot_ms
22
- dot @wpm
23
- end
15
+ def cw_encoding enc
16
+ @cw_encoding.fetch(enc)
17
+ end
24
18
 
25
- def init_print_words_timeout
26
- @start_print_time, @delay_print_time = Time.now, 2.0
27
- end
19
+ def dot wpm
20
+ 1.2 / wpm.to_f
21
+ end
28
22
 
29
- def print_words_timeout?
30
- (Time.now - @start_print_time) > @delay_print_time
31
- end
23
+ def dot_ms
24
+ dot @wpm
25
+ end
32
26
 
33
- def init_play_words_timeout
34
- @start_play_time, @delay_play_time = Time.now, 2.0
35
- end
27
+ def init_print_words_timeout
28
+ @start_print_time, @delay_print_time = Time.now, 2.0
29
+ end
36
30
 
37
- def play_words_timeout?
38
- (Time.now - @start_play_time) > @delay_play_time
39
- end
31
+ def print_words_timeout?
32
+ (Time.now - @start_print_time) > @delay_print_time
33
+ end
40
34
 
41
- def effective_dot_ms
42
- dot @effective_wpm
43
- end
35
+ def effective_dot_ms
36
+ dot @effective_wpm
37
+ end
44
38
 
45
- def init_char_timer
46
- @start_time, @delay_time = Time.now, 0.0
47
- end
39
+ def init_char_timer
40
+ @start_time, @delay_time = Time.now, 0.0
41
+ end
48
42
 
49
- def char_delay_timeout?
50
- (Time.now - @start_time) > @delay_time
51
- end
43
+ def char_delay_timeout?
44
+ (Time.now - @start_time) > @delay_time
45
+ end
52
46
 
53
- def char_timing(* args)
54
- timing = 0
55
- args.flatten.each do |arg|
56
- case arg
57
- when :dot then timing += 2
58
- when :dash then timing += 4
59
- else
60
- puts "Error! invalid morse symbol - was #{arg}"
47
+ def char_timing(* args)
48
+ timing = 0
49
+ args.flatten.each do |arg|
50
+ case arg
51
+ when :dot then timing += 2
52
+ when :dash then timing += 4
53
+ else
54
+ puts "Error! invalid morse symbol - was #{arg}"
55
+ end
61
56
  end
57
+ timing -= 1
58
+ timing = timing.to_f * dot_ms
59
+ timing + code_space_timing
62
60
  end
63
- timing -= 1
64
- timing = timing.to_f * dot_ms
65
- timing + code_space_timing
66
- end
67
61
 
68
- def code_space_timing
69
- @effective_wpm ? 3.0 * effective_dot_ms :
70
- 3.0 * dot_ms
71
- end
62
+ def code_space_timing
63
+ @effective_wpm ? 3.0 * effective_dot_ms :
64
+ 3.0 * dot_ms
65
+ end
72
66
 
73
- def space_timing
74
- space = 4.0
75
- @effective_wpm ? space * effective_dot_ms :
76
- space * dot_ms
77
- end
67
+ def space_timing
68
+ space = 4.0
69
+ @effective_wpm ? space * effective_dot_ms :
70
+ space * dot_ms
71
+ end
78
72
 
79
- def char_delay(char, wpm, ewpm)
80
- @wpm, @effective_wpm = wpm, ewpm
81
- if(char != ' ')
82
- char_timing(cw_encoding(char)) unless(char == ' ')
73
+ def char_delay(char, wpm, ewpm)
74
+ @wpm, @effective_wpm = wpm, ewpm
75
+ if(char != ' ')
76
+ char_timing(cw_encoding(char)) unless(char == ' ')
83
77
  else
84
- space_timing
78
+ space_timing
79
+ end
80
+ end
81
+
82
+ def append_char_delay letr, wpm, ewpm
83
+ @delay_time += char_delay(letr, wpm, ewpm)
85
84
  end
86
- end
87
85
 
88
- def append_char_delay letr, wpm, ewpm
89
- @delay_time += char_delay(letr, wpm, ewpm)
90
86
  end
91
87
 
92
88
  end
@@ -2,200 +2,223 @@
2
2
 
3
3
  require 'wavefile'
4
4
 
5
- class ToneGenerator
5
+ module CWG
6
6
 
7
- include ToneHelpers
7
+ class ToneGenerator
8
8
 
9
- def initialize
10
- @max_amplitude = 0.5
11
- @wpm = Params.wpm.to_f
12
- @frequency = Params.frequency
13
- @effective_wpm = Params.effective_wpm ? Params.effective_wpm.to_f : @wpm
14
- @sample_rate = 2400
15
- @print = Print.new
16
- end
9
+ MUTE = false
17
10
 
18
- def cw_encoding
19
- @encoding ||= CwEncoding.new
20
- end
11
+ include ToneHelpers
12
+ include FileDetails
21
13
 
22
- def progress
23
- @progress ||= Progress.new('Compiling')
24
- end
14
+ def initialize
15
+ @max_amplitude = (Cfg.config["volume"].to_f > 1.0 ?
16
+ 1.0 : Cfg.config["volume"].to_f)
17
+ @wpm = Cfg.config["wpm"].to_f
18
+ @frequency = Cfg.config["frequency"].to_i
19
+ @effective_wpm = Cfg.config["effective_wpm"] ?
20
+ Cfg.config["effective_wpm"].to_f : @wpm
21
+ @sample_rate = 2400
22
+ @print = Print.new
23
+ end
25
24
 
26
- def generate wrds
27
- word_parts(wrds)
28
- # progress.init elements.size * 3 + (wrds.size)
29
- create_element_methods
30
- compile_fundamentals
31
- write_word_parts
32
- end
25
+ def generate wrds
26
+ word_parts(wrds)
27
+ # progress.init elements.size * 3 + (wrds.size)
28
+ create_element_methods
29
+ compile_fundamentals
30
+ write_word_parts
31
+ end
33
32
 
34
- def play
35
- cmd = play_command + ' ' + play_filename
36
- @pid = ! @dry_run ? Process.spawn(cmd) : cmd
37
- end
38
- def data
39
- { :dot => {:name => :dot,
40
- :filename => DOT_FILENAME,
41
- :spb => (@sample_rate * 1.2 / @wpm).to_i },
42
- :dash => {:name => :dash,
43
- :filename => DASH_FILENAME,
44
- :spb => (@sample_rate * 3.6 / @wpm).to_i },
45
- :space => {:name => :space,
46
- :filename => SPACE_FILENAME ,
33
+ def play_filename
34
+ File.join(AUDIO,Cfg.config["audio_filename"])
35
+ end
36
+
37
+ def play
38
+ cmd = play_command + ' ' + play_filename
39
+ @pid = ! @dry_run ? Process.spawn(cmd) : cmd
40
+ end
41
+
42
+ def cw_encoding
43
+ @encoding ||= CwEncoding.new
44
+ end
45
+
46
+ def progress
47
+ @progress ||= Progress.new('Compiling')
48
+ end
49
+
50
+ def data
51
+ { :dot => {:name => :dot,
52
+ :filename => DOT_FILENAME,
47
53
  :spb => (@sample_rate * 1.2 / @wpm).to_i },
48
- :e_space => {:name => :e_space,
49
- :filename => E_SPACE_FILENAME ,
50
- :spb => (@sample_rate * 1.2 / @effective_wpm).to_i }}
51
- end
54
+ :dash => {:name => :dash,
55
+ :filename => DASH_FILENAME,
56
+ :spb => (@sample_rate * 3.6 / @wpm).to_i },
57
+ :space => {:name => :space,
58
+ :filename => SPACE_FILENAME ,
59
+ :spb => (@sample_rate * 1.2 / @wpm).to_i },
60
+ :e_space => {:name => :e_space,
61
+ :filename => E_SPACE_FILENAME ,
62
+ :spb => (@sample_rate * 1.2 / @effective_wpm).to_i }}
63
+ end
52
64
 
53
- def filter_maybe(size, count)
54
- ramp = 0.05
55
- ramp_point = @max_amplitude / ramp
56
- ampl = (count < ramp_point) ? (ramp * count) : @max_amplitude
57
- (count > (size - ramp_point)) ? (ramp * (size - count)) : ampl
58
- end
65
+ def filter_maybe(size, count)
66
+ ramp = 0.05
67
+ ramp_point = @max_amplitude / ramp
68
+ ampl = (count < ramp_point) ? (ramp * count) : @max_amplitude
69
+ (count > (size - ramp_point)) ? (ramp * (size - count)) : ampl
70
+ end
59
71
 
60
- def generate_tone(number_of_samples)
61
- audio_samples = [].fill(0.0, 0, number_of_samples)
62
- number_of_samples.times do |sample_number|
63
- amplitude = filter_maybe(number_of_samples, sample_number)
64
- # amplitude = 1.0 # @max_amplitude
65
- sine_radians = ((@frequency * TWO_PI) / @sample_rate) * sample_number
66
- audio_samples[sample_number] = amplitude * Math.sin(sine_radians)
72
+ def generate_tone(number_of_samples)
73
+ audio_samples = [].fill(0.0, 0, number_of_samples)
74
+ number_of_samples.times do |sample_number|
75
+ amplitude = filter_maybe(number_of_samples, sample_number)
76
+ # amplitude = 1.0 # @max_amplitude
77
+ # amplitude = 0.01 if MUTE
78
+ sine_radians = ((@frequency * TWO_PI) / @sample_rate) * sample_number
79
+ audio_samples[sample_number] = amplitude * Math.sin(sine_radians)
80
+ end
81
+ audio_samples
67
82
  end
68
- audio_samples
69
- end
70
83
 
71
- def generate_buffer audio_samples, ele
72
- WaveFile::Buffer.new(audio_samples, WaveFile::Format.new(:mono, :float, data[ele][:spb]))
73
- end
84
+ def generate_buffer audio_samples, ele
85
+ WaveFile::Buffer.new(audio_samples, WaveFile::Format.new(:mono, :float, data[ele][:spb]))
86
+ end
74
87
 
75
- def write_element_audio_file ele, buffer
76
- WaveFile::Writer.new(data[ele][:filename], WaveFile::Format.new(:mono, :pcm_16, @sample_rate)) do |writer|
77
- writer.write(buffer)
88
+ def write_element_audio_file ele, buffer
89
+ WaveFile::Writer.new(data[ele][:filename], WaveFile::Format.new(:mono, :pcm_16, @sample_rate)) do |writer|
90
+ writer.write(buffer)
91
+ end
78
92
  end
79
- end
80
93
 
81
- def elements
82
- [:dot, :dash, :space, :e_space]
83
- end
94
+ def elements
95
+ [:dot, :dash, :space, :e_space]
96
+ end
84
97
 
85
- def create_element_method ele
86
- define_singleton_method(ele) {data[ele]}
87
- end
98
+ # create dot, dash, space or e_space method
88
99
 
89
- def create_element_methods
90
- elements.each do |ele|
91
- # progress.increment
92
- create_element_method ele
100
+ def create_element_method ele
101
+ define_singleton_method(ele) {data[ele]}
93
102
  end
94
- end
95
103
 
96
- def generate_samples ele
97
- return generate_space(data[ele][:spb]) if space_sample? ele
98
- generate_tone(data[ele][:spb]) unless space_sample? ele
99
- end
104
+ # create dot, dash, space and e_space methods
100
105
 
101
- def compile_fundamentals
102
- elements.each do |ele|
103
- # progress.increment
104
- audio_samples = generate_samples ele
105
- buffer = generate_buffer(audio_samples, ele)
106
- write_element_audio_file ele, buffer
106
+ def create_element_methods
107
+ elements.each do |ele|
108
+ # progress.increment
109
+ create_element_method ele
110
+ end
107
111
  end
108
- end
109
112
 
110
- def space_or_espace
111
- (@effective_wpm == @wpm) ? space : e_space
112
- end
113
+ def generate_samples ele
114
+ return generate_space(data[ele][:spb]) if space_sample? ele
115
+ generate_tone(data[ele][:spb]) unless space_sample? ele
116
+ end
113
117
 
114
- def push_enc chr
115
- arry = []
116
- chr.each_with_index do |c,idx|
117
- arry << c
118
- arry << ((last_element?(idx, chr)) ? (space_or_espace) : space)
118
+ def compile_fundamentals
119
+ elements.each do |ele|
120
+ # progress.increment
121
+ audio_samples = generate_samples ele
122
+ buffer = generate_buffer(audio_samples, ele)
123
+ write_element_audio_file ele, buffer
124
+ end
119
125
  end
120
- arry += char_space
121
- end
122
126
 
123
- def send_char c
124
- enc = nil
125
- if c == ' '
126
- enc = word_space
127
- else
128
- enc = cw_encoding.fetch(c).map { |e| send(e)}
127
+ def space_or_espace
128
+ (@effective_wpm == @wpm) ? space : e_space
129
129
  end
130
- push_enc enc
131
- end
132
130
 
133
- def word_parts str = nil
134
- return @word_parts if @word_parts
135
- @word_parts = []
136
- str.split('').each { |part| @word_parts << part}
137
- @word_parts
138
- end
131
+ def push_enc chr
132
+ arry = []
133
+ chr.each_with_index do |c,idx|
134
+ arry << c
135
+ arry << ((last_element?(idx, chr)) ? (space_or_espace) : space)
136
+ end
137
+ arry += char_space
138
+ end
139
139
 
140
+ def send_char c
141
+ enc = nil
142
+ if c == ' '
143
+ enc = word_space
144
+ else
145
+ enc = cw_encoding.fetch(c).map { |e| send(e)}
146
+ end
147
+ push_enc enc
148
+ end
140
149
 
141
- def make_word_parts
142
- parts = []
143
- @word_parts.each do |part|
144
- # progress.increment
145
- parts += send_char part.downcase
150
+ def word_parts str = nil
151
+ return @word_parts if @word_parts
152
+ @word_parts = []
153
+ str.split('').each { |part| @word_parts << part}
154
+ @word_parts
146
155
  end
147
- parts
148
- end
149
156
 
150
- def prepare_buffers
151
- @buffers = {}
152
- elements.each do |ele|
153
- # progress.increment
154
- @buffers[ele] = []
155
- WaveFile::Reader.new(data[ele][:filename]).
156
- each_buffer(data[ele][:spb]) do |buffer|
157
- @buffers[ele] = buffer
157
+
158
+ def make_word_parts
159
+ parts = []
160
+ @word_parts.each do |part|
161
+ # progress.increment
162
+ parts += send_char part.downcase
158
163
  end
164
+ parts
159
165
  end
160
- end
161
166
 
162
- def write_word_parts
163
- prepare_buffers
164
- write_audio_file
165
- end
167
+ def prepare_buffers
168
+ @buffers = {}
169
+ elements.each do |ele|
170
+ # progress.increment
171
+ @buffers[ele] = []
172
+ WaveFile::Reader.new(data[ele][:filename]).
173
+ each_buffer(data[ele][:spb]) do |buffer|
174
+ @buffers[ele] = buffer
175
+ end
176
+ end
177
+ end
166
178
 
167
- def char_space
168
- @effective_wpm == @wpm ? [space,space] : [e_space,e_space]
169
- end
179
+ def write_word_parts
180
+ prepare_buffers
181
+ write_audio_file
182
+ end
170
183
 
171
- def word_space
172
- @effective_wpm == @wpm ? [space] : [e_space]
173
- end
184
+ def char_space
185
+ @effective_wpm == @wpm ? [space,space] : [e_space,e_space]
186
+ end
174
187
 
175
- def word_composite word
176
- send_char word.downcase
177
- end
188
+ def word_space
189
+ @effective_wpm == @wpm ? [space] : [e_space]
190
+ end
191
+
192
+ def word_composite word
193
+ send_char word.downcase
194
+ end
178
195
 
179
- def write_audio
180
- WaveFile::Writer.new(play_filename, WaveFile::Format.new(:mono, :pcm_16, @sample_rate)) do |writer|
181
- yield.each do |char|
182
- # progress.increment
183
- char.each do |fta|
184
- writer.write(@buffers[fta[:name]])
196
+ def write_audio
197
+ WaveFile::Writer.
198
+ new(play_filename,
199
+ WaveFile::Format.
200
+ new(:mono,
201
+ :pcm_16,
202
+ @sample_rate)) do |writer|
203
+ yield.each do |char|
204
+ # progress.increment
205
+ char.each do |fta|
206
+ writer.write(@buffers[fta[:name]])
207
+ end
185
208
  end
186
209
  end
187
210
  end
188
- end
189
211
 
190
- def reset
191
- @word_parts = @progress = nil
192
- # puts "\r"
193
- end
212
+ def reset
213
+ @word_parts = @progress = nil
214
+ # puts "\r"
215
+ end
194
216
 
195
- def write_audio_file
196
- write_audio { @word_parts.collect {|part| word_composite(part) } }
197
- reset
217
+ def write_audio_file
218
+ write_audio do
219
+ @word_parts.collect {|part| word_composite(part) }
220
+ end
221
+ reset
222
+ end
198
223
  end
199
-
200
224
  end
201
-