JS8Call-Improved master
Loading...
Searching...
No Matches
Detector.h
1#ifndef DETECTOR_HPP__
2#define DETECTOR_HPP__
3
4#include "JS8_Audio/AudioDevice.h"
5
6#include <QMutex>
7#include <vendor/Eigen/Dense>
8
9#include <array>
10
11// Output device that distributes data in predefined chunks via a signal;
12// underlying device for this abstraction is just the buffer that stores
13// samples throughout a receiving period.
14
15class Detector : public AudioDevice {
16 Q_OBJECT;
17
18 // We downsample the input data from 48kHz to 12kHz through this
19 // lowpass FIR filter.
20
21 class Filter final {
22 public:
23 // Amount we're going to downsample; a factor of 4, i.e., 48kHz to
24 // 12kHz, and number of taps in the FIR lowpass filter we're going
25 // to use for the downsample process. These together result in the
26 // amount to shift data in the FIR filter each time we input a new
27 // sample.
28
29 static constexpr std::size_t NDOWN = 48 / 12;
30 static constexpr std::size_t NTAPS = 49;
31 static constexpr std::size_t SHIFT = NTAPS - NDOWN;
32
33 // Our FIR is constructed of a pair of Eigen vectors, each NTAPS in
34 // size. Loading in a sample consists of mapping it to a read-only
35 // view of an Eigen vector, NDOWN in size.
36
37 using Vector = Eigen::Vector<float, NTAPS>;
38 using Sample = Eigen::Map<Eigen::Vector<short, NDOWN> const>;
39
40 // Constructor; we require an array of lowpass FIR coefficients,
41 // equal in size to the number of taps.
42
43 explicit Filter(std::array<Vector::value_type, NTAPS> const &lowpass)
44 : m_w(lowpass.data()), m_t(Vector::Zero()) {}
45
46 // Shift existing data in the lowpass FIR to make room for a new
47 // sample and load it in; downsample through the filter.
48
49 auto downSample(Sample::value_type const *const data) {
50 m_t.head(SHIFT) = m_t.segment(NDOWN, SHIFT);
51 m_t.tail(NDOWN) = Sample(data).cast<Vector::value_type>();
52
53 return static_cast<Sample::value_type>(std::round(m_w.dot(m_t)));
54 }
55
56 private:
57 // Data members
58
59 Eigen::Map<Vector const> m_w;
60 Vector m_t;
61 };
62
63 // Size of a maximally-sized buffer.
64
65 static constexpr std::size_t MaxBufferSize = 7 * 512;
66
67 // A De-interleaved sample buffer big enough for all the
68 // samples for one increment of data (a signals worth) at
69 // the input sample rate.
70
71 using Buffer = std::array<short, MaxBufferSize * Filter::NDOWN>;
72
73 public:
74 // Constructor
75
76 Detector(unsigned frameRate, unsigned periodLengthInSeconds,
77 QObject *parent = nullptr);
78
79 // Inline accessors
80
81 unsigned period() const { return m_period; }
82
83 // Inline manipulators
84
85 QMutex *getMutex() { return &m_lock; }
86 void setTRPeriod(unsigned p) { m_period = p; }
87
88 // Accessors
89
90 unsigned secondInPeriod() const;
91
92 // Manipulators
93
94 void clear();
95 bool reset() override;
96 void resetBufferContent();
98
99 // Signals and slots
100
101 Q_SIGNAL void framesWritten(qint64) const;
102 Q_SLOT void setBlockSize(unsigned);
103
104 protected:
105 // We don't produce data; we're a sink for it.
106
107 qint64 readData(char *, qint64) override { return -1; }
108 qint64 writeData(char const *, qint64) override;
109
110 private:
111 // Data members
112
113 unsigned m_frameRate;
114 unsigned m_period;
115 QMutex m_lock;
116 Filter m_filter;
117 Buffer m_buffer;
118 Buffer::size_type m_bufferPos = 0;
119 std::size_t m_samplesPerFFT = MaxBufferSize;
120 qint32 m_ns = 999;
121};
122
123#endif
bool reset() override
Reset the detector state.
Definition Detector.cpp:85
void resetBufferContent()
Reset the buffer content to zero.
Definition Detector.cpp:148
Detector(unsigned frameRate, unsigned periodLengthInSeconds, QObject *parent=nullptr)
Construct a new Detector object.
Definition Detector.cpp:65
void resetBufferPosition()
Reset the buffer position based on current time.
Definition Detector.cpp:114
unsigned secondInPeriod() const
Get the current second in the period.
Definition Detector.cpp:227
Q_SLOT void setBlockSize(unsigned)
Set the block size for FFT processing.
Definition Detector.cpp:77
void clear()
Clear the detector buffer.
Definition Detector.cpp:96
qint64 writeData(char const *, qint64) override
Write data to the detector buffer.
Definition Detector.cpp:162