Class: CW::ToneGenerator

Inherits:
Object
  • Object
show all
Includes:
FileDetails, ToneHelpers
Defined in:
lib/cw/tone_generator.rb

Defined Under Namespace

Classes: Code

Constant Summary collapse

MUTE =
false

Constants included from FileDetails

FileDetails::ABBREVIATIONS, FileDetails::AUDIO_DIR, FileDetails::BOOKMARK_FILE, FileDetails::CALLS, FileDetails::CALLS_FILENAME, FileDetails::CODE, FileDetails::CODE_FILENAME, FileDetails::CONFIG_FILENAME, FileDetails::CONFIG_PATH, FileDetails::DASH_FILENAME, FileDetails::DATA, FileDetails::DEF_AUDIO_FILENAME, FileDetails::DICT_DIR, FileDetails::DICT_FILENAME, FileDetails::DOT_AUDIO_DIR, FileDetails::DOT_CW_DIR, FileDetails::DOT_FILENAME, FileDetails::E_SPACE_FILENAME, FileDetails::HERE, FileDetails::Q_CODES, FileDetails::ROOT, FileDetails::SPACE_FILENAME, FileDetails::TEXT, FileDetails::USER_CONFIG_PATH, FileDetails::WORK_DIR

Constants included from ToneHelpers

CW::ToneHelpers::TWO_PI

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from FileDetails

#audio_dir, #audio_filename, #dash_path, #default_audio_dir, #dot_audio_dir, #dot_cw_dir, #dot_path, #e_space_path, #init_filenames, #process_audio_dir, #process_dot_audio, #process_dot_cw, #progress_file, #space_path, #user_audio_dir

Methods included from ToneHelpers

#convert_words, #generate_space, #last_element?, #space_sample?

Constructor Details

#initializeToneGenerator

Returns a new instance of ToneGenerator.



38
39
40
41
42
43
44
45
46
47
# File 'lib/cw/tone_generator.rb', line 38

def initialize
  @sample_rate = 2400
  @max_amplitude = (Cfg.config["volume"].to_f > 1.0 ?
                      1.0 : Cfg.config["volume"].to_f)
  @wpm = Cfg.config["wpm"].to_f
  @frequency = Cfg.config["frequency"].to_i
  @effective_wpm = Cfg.config["effective_wpm"] ?
                     Cfg.config["effective_wpm"].to_f : @wpm
  @print = Print.new
end

Instance Attribute Details

#codeObject (readonly)

Returns the value of attribute code.



13
14
15
# File 'lib/cw/tone_generator.rb', line 13

def code
  @code
end

Instance Method Details

#char_spaceObject



166
167
168
# File 'lib/cw/tone_generator.rb', line 166

def char_space
  Array.new(2, word_space)
end

#compile_fundamentalsObject



111
112
113
114
115
116
117
# File 'lib/cw/tone_generator.rb', line 111

def compile_fundamentals
  elements.each do |ele|
    audio_samples = generate_samples ele
    buffer = generate_buffer(audio_samples, ele)
    write_element_audio_file ele, buffer
  end
end

#cw_encodingObject



63
64
65
# File 'lib/cw/tone_generator.rb', line 63

def cw_encoding
  @encoding ||= Encoding.new
end

#elementsObject



102
103
104
# File 'lib/cw/tone_generator.rb', line 102

def elements
  [:dot, :dash, :space, :e_space]
end

#ewpm?Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/cw/tone_generator.rb', line 119

def ewpm?
  @effective_wpm != @wpm
end

#filter_maybe(size, count) ⇒ Object



71
72
73
74
75
76
# File 'lib/cw/tone_generator.rb', line 71

def filter_maybe(size, count)
  ramp = 0.05
  ramp_point =  @max_amplitude / ramp
  ampl = (count < ramp_point) ? (ramp * count) : @max_amplitude
  (count > (size - ramp_point)) ? (ramp * (size - count)) : ampl
end

#formatObject



178
179
180
# File 'lib/cw/tone_generator.rb', line 178

def format
  WaveFile::Format.new(:mono, :pcm_16, @sample_rate)
end

#generate(wrds) ⇒ Object



53
54
55
56
57
# File 'lib/cw/tone_generator.rb', line 53

def generate wrds
  word_parts(wrds)
  compile_fundamentals
  write_word_parts
end

#generate_buffer(audio_samples, ele) ⇒ Object



90
91
92
93
# File 'lib/cw/tone_generator.rb', line 90

def generate_buffer audio_samples, ele
  WaveFile::Buffer.new(audio_samples,
                       WaveFile::Format.new(:mono, :float, code.spb(ele)))
end

#generate_samples(ele) ⇒ Object



106
107
108
109
# File 'lib/cw/tone_generator.rb', line 106

def generate_samples ele
  return generate_space(code.spb(ele)) if space_sample? ele
  generate_tone(code.spb(ele))     unless space_sample? ele
end

#generate_tone(number_of_samples) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/cw/tone_generator.rb', line 78

def generate_tone(number_of_samples)
  audio_samples = [].fill(0.0, 0, number_of_samples)
  number_of_samples.times do |sample_number|
    amplitude = filter_maybe(number_of_samples, sample_number)
    #      amplitude = 1.0 # @max_amplitude
    #      amplitude = 0.01 if MUTE
    sine_radians = ((@frequency * TWO_PI) / @sample_rate) * sample_number
    audio_samples[sample_number] = amplitude * Math.sin(sine_radians)
  end
  audio_samples
end

#play_filenameObject



59
60
61
# File 'lib/cw/tone_generator.rb', line 59

def play_filename
  @play_filename ||= File.join(audio_dir, audio_filename)
end

#prepare_buffersObject



150
151
152
153
154
155
156
157
158
159
# File 'lib/cw/tone_generator.rb', line 150

def prepare_buffers
  @buffers = {}
  elements.each do |ele|
    @buffers[ele] = []
    WaveFile::Reader.new(code.filename(ele))
                    .each_buffer(code.spb(ele)) do |buffer|
      @buffers[ele] = buffer
    end
  end
end

#progressObject



67
68
69
# File 'lib/cw/tone_generator.rb', line 67

def progress
  @progress ||= Progress.new('Compiling')
end

#push_enc(chr) ⇒ Object



127
128
129
130
131
132
133
134
# File 'lib/cw/tone_generator.rb', line 127

def push_enc chr
  arry = []
  chr.each_with_index do |c,idx|
    arry << c
    arry << (last_element?(idx, chr) ? space_or_espace : { name: :space })
  end
  arry += char_space
end

#resetObject



199
200
201
# File 'lib/cw/tone_generator.rb', line 199

def reset
  @word_parts = @progress = nil
end

#send_char(c) ⇒ Object



136
137
138
139
140
141
# File 'lib/cw/tone_generator.rb', line 136

def send_char(c)
  enc = c == ' ' ? [word_space] : cw_encoding.fetch(c).map { |e|
    { :name => e }
  }
  push_enc enc
end

#space_or_espaceObject



123
124
125
# File 'lib/cw/tone_generator.rb', line 123

def space_or_espace
  { name: (ewpm? ? :e_space : :space) }
end

#word_composite(word) ⇒ Object



174
175
176
# File 'lib/cw/tone_generator.rb', line 174

def word_composite(word)
  send_char word.downcase
end

#word_parts(str = nil) ⇒ Object



143
144
145
146
147
148
# File 'lib/cw/tone_generator.rb', line 143

def word_parts(str = nil)
  return @word_parts if @word_parts
  @word_parts = []
  str.split('').each { |part| @word_parts << part }
  @word_parts
end

#word_spaceObject



170
171
172
# File 'lib/cw/tone_generator.rb', line 170

def word_space
  { name: (ewpm? ? :e_space : :space) }
end

#write_audioObject



186
187
188
189
190
# File 'lib/cw/tone_generator.rb', line 186

def write_audio
  WaveFile::Writer.new(play_filename, format) do |writer|
    yield.map { |ch| ch.map { |fta| write_buffer(writer, fta) } }
  end
end

#write_audio_fileObject



192
193
194
195
196
197
# File 'lib/cw/tone_generator.rb', line 192

def write_audio_file
  write_audio do
    @word_parts.collect { |part| word_composite(part) }
  end
  reset
end

#write_buffer(writer, fta) ⇒ Object



182
183
184
# File 'lib/cw/tone_generator.rb', line 182

def write_buffer(writer, fta)
  writer.write(@buffers[fta[:name]])
end

#write_element_audio_file(ele, buffer) ⇒ Object



95
96
97
98
99
100
# File 'lib/cw/tone_generator.rb', line 95

def write_element_audio_file ele, buffer
  WaveFile::Writer.new(code.filename(ele),
                       WaveFile::Format.new(:mono, :pcm_16, @sample_rate)) do |writer|
    writer.write(buffer)
  end
end

#write_word_partsObject



161
162
163
164
# File 'lib/cw/tone_generator.rb', line 161

def write_word_parts
  prepare_buffers
  write_audio_file
end