cw 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
-