Rev 2229 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
964 | jag | 1 | /* |
2 | * morse_code.cc |
||
2302 | jag | 3 | * DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath |
1713 | jag | 4 | * DIN Is Noise is released under GNU Public License 2.0 |
1479 | jag | 5 | * For more information, please visit https://dinisnoise.org/ |
964 | jag | 6 | */ |
7 | |||
8 | |||
9 | #include "morse_code.h" |
||
10 | #include "tokenizer.h" |
||
11 | #include "command.h" |
||
12 | #include "ui_list.h" |
||
13 | #include <algorithm> |
||
2229 | jag | 14 | |
964 | jag | 15 | using namespace std; |
16 | |||
17 | #define result cmdlst.result |
||
18 | |||
19 | extern cmdlist cmdlst; |
||
20 | extern ui_list uis; |
||
21 | extern string user_data_dir; |
||
22 | |||
23 | |||
24 | morse_code::morse_code (const string& ln, const string& sn) : command (ln, sn), dot ("dot.crv"), dash ("dash.crv"), inner_space ("inner.crv"), letter_space ("letter.crv"), word_space ("word.crv"), ed ("morse-code.ed") { |
||
25 | |||
26 | load ("i8n_morse_code"); |
||
27 | |||
28 | ed.add (&dot, &lis); |
||
29 | ed.add (&dash, &lis); |
||
30 | ed.add (&inner_space, &lis); |
||
31 | ed.add (&letter_space, &lis); |
||
32 | ed.add (&word_space, &lis); |
||
33 | |||
34 | add_first_vertex = 1; // of pattern for first letter of sentence. otherwise continue pattern from last added vertex |
||
35 | |||
36 | } |
||
37 | |||
38 | morse_code::~morse_code() { |
||
39 | dot.save ("dot.crv"); |
||
40 | dash.save ("dash.crv"); |
||
2229 | jag | 41 | inner_space.save ("inner_space.crv"); |
42 | letter_space.save ("letter_space.crv"); |
||
43 | word_space.save ("word_space.crv"); |
||
964 | jag | 44 | } |
45 | |||
46 | int morse_code::load (const string& fname) { |
||
47 | |||
48 | ifstream file ((user_data_dir + fname).c_str(), ios::in); |
||
49 | ncodes = 0; |
||
50 | if (file) { |
||
51 | char c; |
||
52 | string dnd; |
||
53 | string ignore; |
||
54 | file >> ignore >> ncodes; |
||
55 | code.clear (); |
||
56 | for (int i = 0; i < ncodes; ++i) { |
||
57 | file >> c >> dnd; |
||
58 | code[c] = dnd; |
||
59 | } |
||
60 | return 1; |
||
61 | } else return 0; |
||
62 | |||
63 | } |
||
64 | |||
65 | int morse_code::operator() (tokenizer& tz) { // called when user executes morse-code <text> [nbeats] |
||
66 | |||
67 | float nbeats; |
||
2228 | jag | 68 | string text; tz >> text >> nbeats; |
964 | jag | 69 | |
70 | std::transform (text.begin(), text.end(), text.begin(), (int(*)(int)) toupper); // morse is upper case |
||
2228 | jag | 71 | return create_pattern (text, nbeats); |
964 | jag | 72 | } |
73 | |||
2228 | jag | 74 | int morse_code::create_pattern (const string& text, float tox) { |
964 | jag | 75 | |
2228 | jag | 76 | multi_curve& morse = curve_editor::copy; |
77 | morse.clear (); |
||
964 | jag | 78 | char prev_let = 0; |
1103 | jag | 79 | |
80 | string outs; |
||
964 | jag | 81 | for (int i = 0, j = text.length(); i < j; ++i) { |
82 | char cur_let = text[i]; |
||
2228 | jag | 83 | if (cur_let == ' ') { |
84 | append (morse, word_space); // word complete |
||
964 | jag | 85 | prev_let = 0; |
1695 | jag | 86 | outs += spc; |
964 | jag | 87 | } else { |
2228 | jag | 88 | if (prev_let != 0) { |
2135 | jag | 89 | append (morse, letter_space); // letter complete |
1695 | jag | 90 | outs += spc; |
2228 | jag | 91 | } |
92 | prev_let = cur_let; |
||
93 | string dnd (code[cur_let]); |
||
94 | outs += dnd; |
||
95 | if (dnd != "") { |
||
96 | char prev_in = 0, cur_in = 0; |
||
97 | for (int m = 0, n = dnd.length(); m < n; ++m) { |
||
98 | cur_in = dnd[m]; |
||
2229 | jag | 99 | if (prev_in != 0) append (morse, inner_space); |
2228 | jag | 100 | prev_in = cur_in; |
101 | if (cur_in == '.') append(morse, dot); else append(morse, dash); |
||
964 | jag | 102 | } |
103 | } |
||
104 | } |
||
105 | } |
||
106 | |||
2229 | jag | 107 | if (tox > 0.0f) scale_tox (morse, tox); |
964 | jag | 108 | |
2228 | jag | 109 | morse.evaluate (); |
110 | result = "morse code for " + text + " (" + outs + ") on copy curve. go paste!"; |
||
964 | jag | 111 | |
2228 | jag | 112 | add_first_vertex = 1; // prep for next time |
2142 | jag | 113 | |
964 | jag | 114 | return 1; |
115 | |||
116 | } |
||
117 | |||
118 | void morse_code::append (multi_curve& m, multi_curve& p) { |
||
119 | |||
2228 | jag | 120 | int n = p.num_vertices; |
121 | if (n == 0) return; |
||
964 | jag | 122 | |
2228 | jag | 123 | point<float> v0 (p.vertices[0]); // first vertex of morse code pattern (dot, dash, letter, word or inner spacings) |
964 | jag | 124 | |
125 | int start = 1; |
||
2228 | jag | 126 | if (add_first_vertex) { // only when we start conversion of text -> morse code. |
964 | jag | 127 | org = v0; |
128 | start = 0; |
||
2228 | jag | 129 | add_first_vertex = 0; |
964 | jag | 130 | } else { // continue pattern from last added vertex in conversion |
2228 | jag | 131 | org = vi; |
964 | jag | 132 | point<float> rt0 (p.right_tangents[0]); |
2228 | jag | 133 | m.set_right_tangent (m.last_vertex, vi.x + (rt0.x - v0.x), vi.y + (rt0.y - v0.y)); |
964 | jag | 134 | } |
135 | |||
136 | // position the vertices & tangents of the pattern |
||
2228 | jag | 137 | for (int i = start; i < n; ++i) { |
964 | jag | 138 | vi = p.vertices[i]; |
139 | point<float>& lt = p.left_tangents[i]; |
||
140 | point<float>& rt = p.right_tangents[i]; |
||
141 | point<float> ltv (lt.x - vi.x, lt.y - vi.y); |
||
142 | point<float> rtv (rt.x - vi.x, rt.y - vi.y); |
||
143 | vi.x = org.x + vi.x - v0.x; |
||
144 | vi.y = org.y + vi.y - v0.y; |
||
145 | m.add_vertex (vi.x, vi.y); |
||
146 | m.add_left_tangent (vi.x + ltv.x, vi.y + ltv.y); |
||
147 | m.add_right_tangent (vi.x + rtv.x, vi.y + rtv.y); |
||
148 | } |
||
149 | |||
150 | } |
||
151 | |||
152 | void morse_code::scale_tox (multi_curve& m, float tox) { |
||
153 | |||
154 | // assumes x is increasing & first vertex x = 0 |
||
155 | // |
||
156 | // suitable when input curve is from waveform, gater, FM/AM and octave shift |
||
157 | // |
||
158 | |||
159 | int n = m.num_vertices; |
||
2228 | jag | 160 | if (n == 0) return; |
964 | jag | 161 | |
162 | int last = n - 1; |
||
163 | point<float> vlast (m.vertices[last]); |
||
164 | |||
165 | float factor = 1.0f; |
||
2129 | jag | 166 | if (vlast.x != 0) factor = tox / vlast.x; |
964 | jag | 167 | |
168 | for (int i = 0; i < n; ++i) { |
||
169 | vi = m.vertices[i]; |
||
2229 | jag | 170 | pointinfo<float>& lt = m.left_tangents[i]; |
171 | int ltp = lt.pin; |
||
172 | pointinfo<float>& rt = m.right_tangents[i]; |
||
173 | int rtp = rt.pin; |
||
174 | lt.pin = rt.pin = 1; |
||
964 | jag | 175 | m.set_vertex (i, vi.x * factor, vi.y); |
176 | m.set_left_tangent (i, lt.x * factor, lt.y); |
||
177 | m.set_right_tangent (i, rt.x * factor, rt.y); |
||
2229 | jag | 178 | lt.pin = ltp; |
179 | rt.pin = rtp; |
||
964 | jag | 180 | } |
181 | |||
2229 | jag | 182 | m.evaluate (); |
183 | |||
964 | jag | 184 | } |