File: Modulator.h

package info (click to toggle)
js8call 2.5.2%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,720 kB
  • sloc: cpp: 562,651; sh: 898; python: 132; ansic: 102; makefile: 4
file content (96 lines) | stat: -rw-r--r-- 2,479 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#ifndef MODULATOR_HPP__
#define MODULATOR_HPP__

#include "JS8_Audio/AudioDevice.h"
#include <QAudio>
#include <QPointer>

class SoundOutput;

/**
 * Audio device that generates PCM audio frames that encode a message.
 *
 * Output can be muted while underway, preserving waveform timing when
 * transmission is resumed.
 *
 * This is intended to run in a thread different from the GUI thread.
 * It is **not** generally thread-safe, see remarks below.
 */
class Modulator final : public AudioDevice {
    Q_OBJECT;

  public:
    enum class State { Synchronizing, Active, Idle };

    // Constructor

    explicit Modulator(QObject *parent = nullptr) : AudioDevice{parent} {}

    // Inline accessors

    /**
     * Whether the device is idle.
     *
     * This method is thread-safe, i.e., can be called from a different thread.
     */
    bool isIdle() const { return m_state.load() == State::Idle; }

    // Manipulators

    void close() override;

    /**
     * Sets the audio frequency.
     *
     * This is **not** by itself thread-safe, but ok if fed
     * via the Qt signalling mechanism.
     */
    Q_SLOT void setAudioFrequency(double const audioFrequency) {
        m_audioFrequency = audioFrequency;
    }

    // Slots

    Q_SLOT void start(double audioFrequency, int submode, double tx_delay,
                      SoundOutput *stream, Channel channel);
    Q_SLOT void stop(bool quick = false);
    Q_SLOT void tune(bool state = true);

  protected:
    // QIODevice protocol

    qint64 readData(char *, qint64) override;
    qint64 writeData(char const *, qint64) override {
        return -1; // we don't consume data
    }

    // In current Qt versions, bytesAvailable() must return a size
    // that exceeds some threshold in order for the AudioSink to go
    // into Active state and start pulling data. This behavior began
    // on Windows with the 6.4 release, on Mac with 6.8, and on Linux
    // with 6.9.
    //
    // See: https://bugreports.qt.io/browse/QTBUG-108672

    qint64 bytesAvailable() const override { return 8000; }

  private:
    // Data members

    QPointer<SoundOutput> m_stream;
    std::atomic<State> m_state = State::Idle;
    bool m_quickClose = false;
    bool m_tuning = false;
    double m_audioFrequency;
    double m_audioFrequency0;
    double m_toneSpacing;
    double m_phi;
    double m_dphi;
    double m_amp;
    double m_nsps;
    qint64 m_silentFrames;
    unsigned m_ic;
    unsigned m_isym0;
};

#endif