Rev 2229 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* morse_code.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "morse_code.h"
#include "tokenizer.h"
#include "command.h"
#include "ui_list.h"
#include <algorithm>
using namespace std;
#define result cmdlst.result
extern cmdlist cmdlst;
extern ui_list uis;
extern string user_data_dir;
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") {
load ("i8n_morse_code");
ed.add (&dot, &lis);
ed.add (&dash, &lis);
ed.add (&inner_space, &lis);
ed.add (&letter_space, &lis);
ed.add (&word_space, &lis);
add_first_vertex = 1; // of pattern for first letter of sentence. otherwise continue pattern from last added vertex
}
morse_code::~morse_code() {
dot.save ("dot.crv");
dash.save ("dash.crv");
inner_space.save ("inner_space.crv");
letter_space.save ("letter_space.crv");
word_space.save ("word_space.crv");
}
int morse_code::load (const string& fname) {
ifstream file ((user_data_dir + fname).c_str(), ios::in);
ncodes = 0;
if (file) {
char c;
string dnd;
string ignore;
file >> ignore >> ncodes;
code.clear ();
for (int i = 0; i < ncodes; ++i) {
file >> c >> dnd;
code[c] = dnd;
}
return 1;
} else return 0;
}
int morse_code::operator() (tokenizer& tz) { // called when user executes morse-code <text> [nbeats]
float nbeats;
string text; tz >> text >> nbeats;
std::transform (text.begin(), text.end(), text.begin(), (int(*)(int)) toupper); // morse is upper case
return create_pattern (text, nbeats);
}
int morse_code::create_pattern (const string& text, float tox) {
multi_curve& morse = curve_editor::copy;
morse.clear ();
char prev_let = 0;
string outs;
for (int i = 0, j = text.length(); i < j; ++i) {
char cur_let = text[i];
if (cur_let == ' ') {
append (morse, word_space); // word complete
prev_let = 0;
outs += spc;
} else {
if (prev_let != 0) {
append (morse, letter_space); // letter complete
outs += spc;
}
prev_let = cur_let;
string dnd (code[cur_let]);
outs += dnd;
if (dnd != "") {
char prev_in = 0, cur_in = 0;
for (int m = 0, n = dnd.length(); m < n; ++m) {
cur_in = dnd[m];
if (prev_in != 0) append (morse, inner_space);
prev_in = cur_in;
if (cur_in == '.') append(morse, dot); else append(morse, dash);
}
}
}
}
if (tox > 0.0f) scale_tox (morse, tox);
morse.evaluate ();
result = "morse code for " + text + " (" + outs + ") on copy curve. go paste!";
add_first_vertex = 1; // prep for next time
return 1;
}
void morse_code::append (multi_curve& m, multi_curve& p) {
int n = p.num_vertices;
if (n == 0) return;
point<float> v0 (p.vertices[0]); // first vertex of morse code pattern (dot, dash, letter, word or inner spacings)
int start = 1;
if (add_first_vertex) { // only when we start conversion of text -> morse code.
org = v0;
start = 0;
add_first_vertex = 0;
} else { // continue pattern from last added vertex in conversion
org = vi;
point<float> rt0 (p.right_tangents[0]);
m.set_right_tangent (m.last_vertex, vi.x + (rt0.x - v0.x), vi.y + (rt0.y - v0.y));
}
// position the vertices & tangents of the pattern
for (int i = start; i < n; ++i) {
vi = p.vertices[i];
point<float>& lt = p.left_tangents[i];
point<float>& rt = p.right_tangents[i];
point<float> ltv (lt.x - vi.x, lt.y - vi.y);
point<float> rtv (rt.x - vi.x, rt.y - vi.y);
vi.x = org.x + vi.x - v0.x;
vi.y = org.y + vi.y - v0.y;
m.add_vertex (vi.x, vi.y);
m.add_left_tangent (vi.x + ltv.x, vi.y + ltv.y);
m.add_right_tangent (vi.x + rtv.x, vi.y + rtv.y);
}
}
void morse_code::scale_tox (multi_curve& m, float tox) {
// assumes x is increasing & first vertex x = 0
//
// suitable when input curve is from waveform, gater, FM/AM and octave shift
//
int n = m.num_vertices;
if (n == 0) return;
int last = n - 1;
point<float> vlast (m.vertices[last]);
float factor = 1.0f;
if (vlast.x != 0) factor = tox / vlast.x;
for (int i = 0; i < n; ++i) {
vi = m.vertices[i];
pointinfo<float>& lt = m.left_tangents[i];
int ltp = lt.pin;
pointinfo<float>& rt = m.right_tangents[i];
int rtp = rt.pin;
lt.pin = rt.pin = 1;
m.set_vertex (i, vi.x * factor, vi.y);
m.set_left_tangent (i, lt.x * factor, lt.y);
m.set_right_tangent (i, rt.x * factor, rt.y);
lt.pin = ltp;
rt.pin = rtp;
}
m.evaluate ();
}