Skip to content

Commit

Permalink
Added inter-char/inter-word pause and text settings.
Browse files Browse the repository at this point in the history
  • Loading branch information
hmatuschek committed Feb 21, 2019
1 parent b54d209 commit f3d1c81
Show file tree
Hide file tree
Showing 13 changed files with 323 additions and 69 deletions.
26 changes: 13 additions & 13 deletions qso/qcodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,28 @@
<one-of>
<t w="01">aa</t> <t w="01">ab</t> <t w="10">abt</t> <t w="10">adr</t> <t w="30">agn</t>
<t w="01">anr</t> <t w="20">ant</t> <t w="01">arnd</t> <t w="10">bci</t> <t w="01">bcnu</t>
<t w="10">bk</t> <t w="01">bn</t> <t w="10">btr</t> <t w="20">btu</t> <t w="01">bug</t>
<t w="10">bk</t> <t w="01">bn</t> <t w="10">btr</t> <t w="20">btu</t> <t w="05">bug</t>
<t w="20">buro</t> <t w="10">b4</t> <t w="30">c</t> <t w="01">cba</t> <t w="10">cfm</t>
<t w="01">ck</t> <t w="01">cl</t> <t w="10">condx</t> <t w="01">cos</t> <t w="30">cq</t>
<t w="01">cs</t> <t w="10">ctl</t> <t w="01">cud</t> <t w="20">cul</t> <t w="20">cw</t>
<t w="01">ck</t> <t w="05">cl</t> <t w="10">condx</t> <t w="01">cos</t> <t w="30">cq</t>
<t w="01">cs</t> <t w="10">ctl</t> <t w="05">cud</t> <t w="20">cul</t> <t w="20">cw</t>
<t w="01">cx</t> <t w="30">de</t> <t w="01">dn</t> <t w="30">dr</t> <t w="01">dsw</t>
<t w="20">dx</t> <t w="01">emrg</t> <t w="01">enuf</t> <t w="30">es</t> <t w="30">fb</t>
<t w="30">fer</t> <t w="01">fm</t> <t w="10">freq</t> <t w="10">fwd</t> <t w="30">ga</t>
<t w="30">fer</t> <t w="20">fr</t> <t w="01">fm</t> <t w="10">freq</t> <t w="10">fwd</t> <t w="30">ga</t>
<t w="30">ge</t> <t w="01">gg</t> <t w="30">gl</t> <t w="30">gm</t> <t w="01">gnd</t>
<t w="01">gud</t> <t w="10">hee</t> <t w="30">hi</t> <t w="30">hr</t> <t w="10">hv</t>
<t w="30">hw</t> <t w="20">ii</t> <t w="01">imp</t> <t w="30">k</t> <t w="01">lid</t>
<t w="01">mh</t> <t w="01">mils</t> <t w="10">mni</t> <t w="01">msg</t> <t w="01">n</t>
<t w="01">mh</t> <t w="01">mils</t> <t w="10">mni</t> <t w="10">msg</t> <t w="10">n</t>
<t w="01">nil</t> <t w="30">nr</t> <t w="01">nw</t> <t w="10">ok</t> <t w="30">om</t>
<t w="30">op</t> <t w="01">pls</t> <t w="30">pse</t> <t w="20">pwr</t> <t w="01">px</t>
<t w="30">op</t> <t w="10">pls</t> <t w="30">pse</t> <t w="20">pwr</t> <t w="01">px</t>
<t w="20">rr</t> <t w="10">rx</t> <t w="01">rfi</t> <t w="20">rig</t> <t w="20">rpt</t>
<t w="01">rprt</t> <t w="30">rst</t> <t w="10">sae</t> <t w="10">sase</t> <t w="01">sed</t>
<t w="01">sfr</t> <t w="10">sig</t> <t w="10">sigs</t> <t w="05">sk</t> <t w="05">sked</t>
<t w="01">snr</t> <t w="20">sri</t> <t w="05">ssb</t> <t w="10">stn</t> <t w="20">temp</t>
<t w="01">tfc</t> <t w="01">tks</t> <t w="01">tmw</t> <t w="20">tnx</t> <t w="01">tre</t>
<t w="01">tt</t> <t w="30">tu</t> <t w="01">tvi</t> <t w="01">tx</t> <t w="10">trx</t>
<t w="10">rprt</t> <t w="30">rst</t> <t w="10">sae</t> <t w="10">sase</t> <t w="01">sed</t>
<t w="01">sfr</t> <t w="10">sig</t> <t w="10">sigs</t> <t w="05">sk</t> <t w="10">sked</t>
<t w="05">snr</t> <t w="20">sri</t> <t w="05">ssb</t> <t w="10">stn</t> <t w="20">temp</t>
<t w="01">tfc</t> <t w="10">tks</t> <t w="01">tmw</t> <t w="20">tnx</t> <t w="01">tre</t>
<t w="01">tt</t> <t w="30">tu</t> <t w="05">tvi</t> <t w="10">tx</t> <t w="10">trx</t>
<t w="10">ufb</t> <t w="20">ur</t> <t w="10">urs</t> <t w="01">vx</t> <t w="20">vy</t>
<t w="01">wa</t> <t w="01">wb</t> <t w="10">wkd</t> <t w="20">wx</t> <t w="10">xyl</t>
<t w="10">yl</t> <t w="01">yr</t> <t w="30">73</t> <t w="10">88</t> <t w="10">55</t>
<t w="10">yl</t> <t w="10">yr</t> <t w="20">73</t> <t w="10">88</t> <t w="10">55</t>
</one-of>
</rule>

Expand All @@ -44,7 +44,7 @@
<i w="10"><apply rule="qcode"/></i>
<i w="50"><apply rule="abbr"/></i>
</one-of>
<p/><p/>
<t> </t>
</rep>
<bt/><stop/>
</rep>
Expand Down
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
set(kochmorse_SOURCES main.cc qhal.cc
globals.cc audiosink.cc effect.cc morseencoder.cc tutor.cc application.cc mainwindow.cc
settings.cc aboutdialog.cc listwidget.cc morsedecoder.cc textgen.cc qsochat.cc qrm.cc
checkupdate.cc)
checkupdate.cc colorbutton.cc)
set(kochmorse_MOC_HEADERS
audiosink.hh effect.hh morseencoder.hh tutor.hh application.hh mainwindow.hh settings.hh
aboutdialog.hh listwidget.hh morsedecoder.hh textgen.hh qsochat.hh qrm.hh
checkupdate.hh)
checkupdate.hh colorbutton.hh)
set(kochmorse_HEADERS globals.hh qhal.hh ${kochmorse_MOC_HEADERS})

qt5_wrap_cpp(kochmorse_MOC_SOURCES ${kochmorse_MOC_HEADERS})
Expand Down
7 changes: 4 additions & 3 deletions src/application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Application::Application(int &argc, char *argv[])
settings.fadingMaxDamp(), settings.fadingRate(), this);

_encoder = new MorseEncoder(settings.tone(), settings.tone()+settings.dashPitch(),
settings.speed(), settings.effSpeed(), settings.sound(),
settings.jitter(), this);
settings.speed(), settings.icPauseFactor(), settings.iwPauseFactor(),
settings.sound(), settings.jitter(), this);

_audio_sink->setSource(_noiseEffect);
_noiseEffect->setSource(_qrm);
Expand Down Expand Up @@ -155,7 +155,8 @@ Application::applySettings()

// Reconfigure encoder
_encoder->setSpeed(settings.speed());
_encoder->setEffSpeed(settings.effSpeed());
_encoder->setICPFactor(settings.icPauseFactor());
_encoder->setIWPFactor(settings.iwPauseFactor());
_encoder->setDotTone(settings.tone());
_encoder->setDashTone(settings.tone()+settings.dashPitch());
_encoder->setSound(settings.sound());
Expand Down
30 changes: 30 additions & 0 deletions src/colorbutton.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "colorbutton.hh"

ColorButton::ColorButton(const QColor &color, QWidget *parent)
: QToolButton(parent), _color(color)
{
setColor(color);
connect(this, SIGNAL(clicked()), this, SLOT(_onSelectColor()));
}

const QColor &
ColorButton::color() const {
return _color;
}

void
ColorButton::setColor(const QColor &color) {
_color = color;
QPixmap pixmap(64,64);
pixmap.fill(_color);
setIcon(QIcon(pixmap));
}

void
ColorButton::_onSelectColor() {
QColorDialog dialog(_color);
if (QDialog::Accepted != dialog.exec())
return;
setColor(dialog.currentColor());
}

26 changes: 26 additions & 0 deletions src/colorbutton.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef COLORBUTTON_HH
#define COLORBUTTON_HH

#include <QToolButton>
#include <QColorDialog>
#include <QColor>


class ColorButton : public QToolButton
{
Q_OBJECT

public:
explicit ColorButton(const QColor &color, QWidget *parent=nullptr);

const QColor &color() const;
void setColor(const QColor &color);

protected slots:
void _onSelectColor();

protected:
QColor _color;
};

#endif // COLORBUTTON_HH
1 change: 1 addition & 0 deletions src/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ inline QHash<QChar, QString> _initProsignTable() {
table[QChar(0x2403)] = "SK"; // SK -> ETX
table[QChar(0x2406)] = "SN"; // SN -> ACK
table[QChar(0x2407)] = "KN"; // KN -> BEL
table[QChar('\t')] = " "; // TAB -> " "
return table;
}

Expand Down
14 changes: 9 additions & 5 deletions src/mainwindow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ MainWindow::MainWindow(Application &app, QWidget *parent)
// Assemble text view
_text = new QTextEdit();
_text->setMinimumSize(640,230);
QFont f = _text->document()->defaultFont();
f.setFamily("Courier");
f.setPointSize(14);
f.setStyleHint(QFont::Monospace);
_text->document()->setDefaultFont(f);
_text->document()->setDefaultFont(settings.textFont());
_text->setReadOnly(true);
_text->setTextInteractionFlags(Qt::NoTextInteraction);
_text->setTabStopDistance(35);

// Play button
_play = new QAction(
Expand Down Expand Up @@ -118,7 +115,12 @@ MainWindow::onSessionFinished() {
void
MainWindow::onCharSend(QString ch) {
// Update text-field
QTextCharFormat old = _text->currentCharFormat();
QTextCharFormat fmt = old;
fmt.setForeground(QColor("black"));
_text->setCurrentCharFormat(fmt);
_text->insertPlainText(ch);
_text->setCurrentCharFormat(old);
}

void
Expand All @@ -134,8 +136,10 @@ MainWindow::onCharReceived(QString ch) {

void
MainWindow::onPlayToggled(bool play) {
Settings settings;
if (play) {
_text->document()->clear();
_text->document()->setDefaultFont(settings.textFont());
_app.startSession();
} else {
_app.stopSession();
Expand Down
38 changes: 26 additions & 12 deletions src/morseencoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#include <QByteArray>


MorseEncoder::MorseEncoder(double ditFreq, double daFreq, double speed, double effSpeed,
MorseEncoder::MorseEncoder(double ditFreq, double daFreq, double speed, double icpFac, double iwpFac,
Sound sound, Jitter jitter, QObject *parent)
: QIODevice(parent), _ditFreq(ditFreq), _daFreq(daFreq), _speed(speed), _effSpeed(effSpeed),
_sound(sound), _jitter(jitter), _unitLength(0), _effUnitLength(0), _ditSamples(4), _daSamples(4),
: QIODevice(parent), _ditFreq(ditFreq), _daFreq(daFreq), _speed(speed), _icpfac(icpFac), _iwpfac(iwpFac),
_sound(sound), _jitter(jitter), _unitLength(0), _ditSamples(4), _daSamples(4),
_icPause(), _iwPause(), _current(0), _queue(), _tsend(0), _played(0)
{
_createSamples();
Expand All @@ -18,12 +18,14 @@ MorseEncoder::MorseEncoder(double ditFreq, double daFreq, double speed, double e
void
MorseEncoder::_createSamples()
{
// ensure effective speed is <= speed
_effSpeed = std::min(_speed, _effSpeed);
// ensure effective pause factors are >= 1
_icpfac = std::max(1.0, _icpfac);
_iwpfac = std::max(1.0, _iwpfac);

// Compute unit (dit) length (PARIS std. = 50 units per word) in samples
// including 10 dits inter-character pauses (excl. 1 dit pause after last symbol) and
// and 5 dits inter-word pause (excl. 1+2 dit pause after last char).
_unitLength = size_t((60.*Globals::sampleRate)/(50.*_speed));
_effUnitLength = size_t((60.*Globals::sampleRate)/(50.*_effSpeed));

// The first and last epsilon samples are windowed
size_t epsilon = 0;
Expand Down Expand Up @@ -92,15 +94,15 @@ MorseEncoder::_createSamples()
daData[i] = 0;
}

// Compute inter-char pause (3 x effUnit, not incl. pause after symbol (dit or da))
size_t icPauseLength = 3*_effUnitLength-_unitLength;
// Compute inter-char pause (3 x dit, not incl. pause after symbol (dit or da))
size_t icPauseLength = (3*_icpfac*_unitLength)-_unitLength;
_icPause.resize(icPauseLength*sizeof(int16_t));
int16_t *icPauseData = reinterpret_cast<int16_t *>(_icPause.data());
for (size_t i=0; i<icPauseLength; i++)
icPauseData[i] = 0;

// Compute inter-word pause (7 x effUnit, not incl. pause after last char)
size_t iwPauseLength = 7*_effUnitLength - icPauseLength;
size_t iwPauseLength = (7*_iwpfac*_unitLength) - 2*_unitLength;
_iwPause.resize(iwPauseLength*sizeof(int16_t));
int16_t *iwPauseData = reinterpret_cast<int16_t *>(_iwPause.data());
for (size_t i=0; i<iwPauseLength; i++)
Expand All @@ -123,7 +125,7 @@ MorseEncoder::send(const QString &text) {

void
MorseEncoder::send(QChar ch) {
if ((! Globals::charTable.contains(ch)) && (' ' != ch) && ('\n' != ch))
if ((! Globals::charTable.contains(ch)) && (' ' != ch) && ('\n' != ch) && ('\t'!=ch))
return;
bool empty = _queue.isEmpty();
_queue.append(ch);
Expand Down Expand Up @@ -163,8 +165,12 @@ MorseEncoder::setSpeed(int speed) {
}

void
MorseEncoder::setEffSpeed(int speed) {
_effSpeed = speed; _createSamples();
MorseEncoder::setICPFactor(double factor) {
_icpfac = factor; _createSamples();
}
void
MorseEncoder::setIWPFactor(double factor) {
_iwpfac = factor; _createSamples();
}


Expand Down Expand Up @@ -212,6 +218,14 @@ MorseEncoder::_send()
// Update time
_tsend += double(1000*_iwPause.size())/(2*Globals::sampleRate);
return;
} else if ('\t' == _current) {
// "play" inter-word pause 3x
_buffer.append(_iwPause);
_buffer.append(_iwPause);
_buffer.append(_iwPause);
// Update time
_tsend += double(1000*3*_iwPause.size())/(2*Globals::sampleRate);
return;
}

// Get code
Expand Down
19 changes: 11 additions & 8 deletions src/morseencoder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ public:
* @param ditFreq Specifies the tone freqency of a dot (dit).
* @param daFreq Specifies the tone frequency of a dash (da).
* @param speed Specifies the character speed (in WPM).
* @param effSpeed Specifies the pause speed (in WPM).
* @param icpFac Specifies the inter-char pause factor (>=1).
* @param iwpFac Specifies the inter-word pause factor (>=1).
* @param jitter Specifies the dit/da length jitter.
* @param parent Specifies the @c QObject parent. */
explicit MorseEncoder(double ditFreq, double daFreq, double speed, double effSpeed,
explicit MorseEncoder(double ditFreq, double daFreq, double speed, double icpFac, double iwpFac,
Sound sound, Jitter jitter=JITTER_EXACT, QObject *parent=nullptr);

/** Sends the given text. */
Expand All @@ -59,8 +60,10 @@ public:
void resetTime();
/** (Re-) Sets the character speed. */
void setSpeed(int speed);
/** (Re-) Sets the effective (pause) speed. */
void setEffSpeed(int speed);
/** (Re-) Sets the inter-char pause factor. */
void setICPFactor(double factor);
/** (Re-) Sets the inter-word pause factor. */
void setIWPFactor(double factor);
/** (Re-) Sets the dot-tone (dit) frequency. */
void setDotTone(double freq);
/** (Re-) Sets the dash-tone (da) frequency. */
Expand Down Expand Up @@ -98,17 +101,17 @@ protected:

/** Char speed in WPM. */
double _speed;
/** Effective speed (pauses) in WPM. */
double _effSpeed;
/** Inter-char pause factor. */
double _icpfac;
/** Inter-word pause factor. */
double _iwpfac;
/** The sound variant. */
Sound _sound;
/** The jitter. */
Jitter _jitter;

/** Length of a "dit" in samples. */
size_t _unitLength;
/** Pause length in samples. */
size_t _effUnitLength;

/** A "dit" incl. inter-symbol pause. */
QVector<QByteArray> _ditSamples;
Expand Down
4 changes: 2 additions & 2 deletions src/qrm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ QRMGenerator::QRMGenerator(QIODevice *source, size_t num, double snr, QObject *p
for (size_t i=0; i<_num; i++) {
double f = ((rand() % 700) + 300), wpm = 15 + (rand() % 10);
MorseEncoder::Jitter jitter = MorseEncoder::Jitter(rand()%4);
_encoder[i] = new MorseEncoder(f, f, wpm, wpm, MorseEncoder::SOUND_SHARP, jitter, this);
_encoder[i] = new MorseEncoder(f, f, wpm, 1., 1., MorseEncoder::SOUND_SHARP, jitter, this);
_encoder[i]->open(QIODevice::ReadOnly);
_generator[i] = new GenTextTutor(_encoder[i], ":/qso/qsogen.xml", this);
connect(_generator[i], SIGNAL(sessionComplete()), _generator[i], SLOT(start()));
Expand Down Expand Up @@ -59,7 +59,7 @@ QRMGenerator::setStations(int num) {
for (size_t i=0; i<_num; i++) {
double f = ((rand() % 700) + 300), wpm = 15 + (rand() % 10);
MorseEncoder::Jitter jitter = MorseEncoder::Jitter(rand()%4);
_encoder[i] = new MorseEncoder(f, f, wpm, wpm, MorseEncoder::SOUND_SHARP, jitter, this);
_encoder[i] = new MorseEncoder(f, f, wpm, 1.0, 1.0, MorseEncoder::SOUND_SHARP, jitter, this);
_encoder[i]->open(QIODevice::ReadOnly);
_generator[i] = new GenTextTutor(_encoder[i], ":/qso/qsogen.xml", this);
connect(_generator[i], SIGNAL(sessionComplete()), _generator[i], SLOT(start()));
Expand Down
Loading

0 comments on commit f3d1c81

Please sign in to comment.