Skip to content

Commit 84da183

Browse files
Merge pull request #1310 from AlexandreRouma/master
New sink/stream system
2 parents 0144d8e + a9e59bd commit 84da183

File tree

61 files changed

+2799
-826
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2799
-826
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ assignees: ''
77

88
---
99

10+
# WARNING: Filling out the template below is NOT optional. Issues not filling out this template will be closed without review.
11+
1012
FIRST: Before reporting any bug, make sure that the bug you are reporting has not been reported before. Also, try to use the [nightly version](https://www.sdrpp.org/nightly) if possible in case I've already fixed the bug.
1113

1214
**Hardware**

.github/pull_request_template.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
# Important
22

3-
Only minor bug fixes and bandplans are accepted.
4-
5-
Pull requests adding features or any bug fix that requires significant code changes will be automatically rejected.
6-
3+
Only bandplan, colormaps and themes are accepted. Code pull requests are **NOT welcome**.
74
Open an issue requesting a feature or discussing a possible bugfix instead.

.github/workflows/build_all.yml

+59-36
Large diffs are not rendered by default.

contributing.md

+5-64
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,6 @@
11
# Pull Requests
22

3-
**I DO NOT ACCEPT PULL-REQUEST FOR FEATURES OR BUGFIXES REQUIRING SIGNIFICANT CODE/STRUCTURE CHANGES.**
4-
**SUCH PULL REQUESTS WILL BE CLOSED AUTOMATICALLY. OPEN AN ISSUE DETAILING FEATURE REQUESTS OR POTENTIAL BUGFIX INSTEAD.**
5-
6-
# Code Style
7-
8-
## Naming Convention
9-
10-
- Files: `snake_case.h` `snake_case.cpp`
11-
- Namespaces: `CamelCase`
12-
- Classes: `CamelCase`
13-
- Structs: `CamelCase_t`
14-
- Members: `camelCase`
15-
- Enum: `SNAKE_CASE`
16-
- Macros: `SNAKE_CASE`
17-
18-
## Brace Style
19-
20-
```c++
21-
int myFunction() {
22-
if (shortIf) { shortFunctionName(); }
23-
24-
if (longIf) {
25-
longFunction();
26-
otherStuff();
27-
myLongFunction();
28-
}
29-
}
30-
```
31-
32-
Note: If it makes the code cleaner, remember to use the `?` keyword instead of a `if else` statement.
33-
34-
## Pointers
35-
36-
Please use `type* name` for pointers.
37-
38-
## Structure
39-
40-
Headers and their associated C++ files shall be in the same directory. All headers must use `#pragma once` instead of other include guards. Only include files in a header that are being used in that header. Include the rest in the associated C++ file.
41-
42-
# Modules
43-
44-
## Module Naming Convention
45-
46-
All modules names must be `snake_case`. If the module is a source, it must end with `_source`. If it is a sink, it must end with `_sink`.
47-
48-
For example, lets take the module named `cool_source`:
49-
50-
- Directory: `cool_source`
51-
- Class: `CoolSourceModule`
52-
- Binary: `cool_source.<os dynlib extension>`
53-
54-
## Integration into main repository
55-
56-
If the module meets the code quality requirements, it may be added to the official repository. A module that doesn't require any external dependencies that the core doesn't already use may be enabled for build by default. Otherwise, they must be disabled for build by default with a `OPT_BUILD_MODULE_NAME` variable set to `OFF`.
57-
58-
# JSON Formatting
59-
60-
The ability to add new radio band allocation identifiers and color maps relies on JSON files. Proper formatting of these JSON files is important for reference and readability. The following guides will show you how to properly format the JSON files for their respective uses.
61-
62-
**IMPORTANT: JSON File cannot contain comments, there are only in this example for clarity**
3+
Code pull requests are **NOT welcome**. Please open an issue discussing potential bugfixes or feature requests instead.
634

645
## Band Frequency Allocation
656

@@ -119,8 +60,8 @@ Please follow this guide to properly format the JSON files for custom color maps
11960
}
12061
```
12162

122-
# Best Practices
63+
# JSON Formatting
64+
65+
The ability to add new radio band allocation identifiers and color maps relies on JSON files. Proper formatting of these JSON files is important for reference and readability. The following guides will show you how to properly format the JSON files for their respective uses.
12366

124-
* All additions and/or bug fixes to the core must not add additional dependencies.
125-
* Use VSCode for development, VS seems to cause issues.
126-
* DO NOT use libboost for any code meant for this repository
67+
**IMPORTANT: JSON File cannot contain comments, there are only in this example for clarity**

core/libcorrect/src/convolutional/history_buffer.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ uint8_t *history_buffer_get_slice(history_buffer *buf) { return buf->history[buf
4545

4646
shift_register_t history_buffer_search(history_buffer *buf, const distance_t *distances,
4747
unsigned int search_every) {
48-
shift_register_t bestpath;
48+
shift_register_t bestpath = 0;
4949
distance_t leasterror = USHRT_MAX;
5050
// search for a state with the least error
5151
for (shift_register_t state = 0; state < buf->num_states; state += search_every) {

core/src/command_args.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ int CommandArgsParser::parse(int argc, char* argv[]) {
8888
try {
8989
carg.ival = std::stoi(arg);
9090
}
91-
catch (std::exception e) {
91+
catch (const std::exception& e) {
9292
printf("Invalid argument, failed to parse integer\n");
9393
showHelp();
9494
return -1;
@@ -98,7 +98,7 @@ int CommandArgsParser::parse(int argc, char* argv[]) {
9898
try {
9999
carg.fval = std::stod(arg);
100100
}
101-
catch (std::exception e) {
101+
catch (const std::exception& e) {
102102
printf("Invalid argument, failed to parse float\n");
103103
showHelp();
104104
return -1;

core/src/config.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ void ConfigManager::load(json def, bool lock) {
3636
file >> conf;
3737
file.close();
3838
}
39-
catch (std::exception e) {
40-
flog::error("Config file '{0}' is corrupted, resetting it", path);
39+
catch (const std::exception& e) {
40+
flog::error("Config file '{}' is corrupted, resetting it: {}", path, e.what());
4141
conf = def;
4242
save(false);
4343
}

core/src/dsp/chain.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ namespace dsp {
9393
void disableBlock(Processor<T, T>* block, Func onOutputChange) {
9494
// Check that the block is part of the chain
9595
if (!blockExists(block)) {
96-
throw std::runtime_error("[chain] Tried to enable a block that isn't part of the chain");
96+
throw std::runtime_error("[chain] Tried to disable a block that isn't part of the chain");
9797
}
9898

9999
// If already disabled, don't do anything
@@ -163,10 +163,12 @@ namespace dsp {
163163

164164
private:
165165
Processor<T, T>* blockBefore(Processor<T, T>* block) {
166+
// TODO: This is wrong and must be fixed when I get more time
166167
for (auto& ln : links) {
167168
if (ln == block) { return NULL; }
168169
if (states[ln]) { return ln; }
169170
}
171+
return NULL;
170172
}
171173

172174
Processor<T, T>* blockAfter(Processor<T, T>* block) {

core/src/dsp/demod/broadcast_fm.h

+21-31
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,17 @@ namespace dsp::demod {
4949
audioFirTaps = taps::lowPass(15000.0, 4000.0, _samplerate);
5050
alFir.init(NULL, audioFirTaps);
5151
arFir.init(NULL, audioFirTaps);
52+
xlator.init(NULL, -57000.0, samplerate);
5253
rdsResamp.init(NULL, samplerate, 5000.0);
5354

5455
lmr = buffer::alloc<float>(STREAM_BUFFER_SIZE);
5556
l = buffer::alloc<float>(STREAM_BUFFER_SIZE);
5657
r = buffer::alloc<float>(STREAM_BUFFER_SIZE);
5758

5859
lprDelay.out.free();
59-
lmrDelay.out.free();
6060
arFir.out.free();
6161
alFir.out.free();
62+
xlator.out.free();
6263
rdsResamp.out.free();
6364

6465
base_type::init(in);
@@ -92,6 +93,7 @@ namespace dsp::demod {
9293
alFir.setTaps(audioFirTaps);
9394
arFir.setTaps(audioFirTaps);
9495

96+
xlator.setOffset(-57000.0, samplerate);
9597
rdsResamp.setInSamplerate(samplerate);
9698

9799
reset();
@@ -139,7 +141,7 @@ namespace dsp::demod {
139141
base_type::tempStart();
140142
}
141143

142-
inline int process(int count, complex_t* in, stereo_t* out, int& rdsOutCount, float* rdsout = NULL) {
144+
inline int process(int count, complex_t* in, stereo_t* out, int& rdsOutCount, complex_t* rdsout = NULL) {
143145
// Demodulate
144146
demod.process(count, in, demod.out.writeBuf);
145147
if (_stereo) {
@@ -152,24 +154,24 @@ namespace dsp::demod {
152154

153155
// Delay
154156
lprDelay.process(count, demod.out.writeBuf, demod.out.writeBuf);
155-
lmrDelay.process(count, rtoc.out.writeBuf, rtoc.out.writeBuf);
157+
lmrDelay.process(count, rtoc.out.writeBuf, lmrDelay.out.writeBuf);
156158

157159
// conjugate PLL output to down convert twice the L-R signal
158160
math::Conjugate::process(count, pilotPLL.out.writeBuf, pilotPLL.out.writeBuf);
159-
math::Multiply<dsp::complex_t>::process(count, rtoc.out.writeBuf, pilotPLL.out.writeBuf, rtoc.out.writeBuf);
160-
math::Multiply<dsp::complex_t>::process(count, rtoc.out.writeBuf, pilotPLL.out.writeBuf, rtoc.out.writeBuf);
161+
math::Multiply<dsp::complex_t>::process(count, lmrDelay.out.writeBuf, pilotPLL.out.writeBuf, lmrDelay.out.writeBuf);
162+
math::Multiply<dsp::complex_t>::process(count, lmrDelay.out.writeBuf, pilotPLL.out.writeBuf, lmrDelay.out.writeBuf);
161163

162164
// Do RDS demod
163165
if (_rdsOut) {
164-
// Since the PLL output is no longer needed after this, use it as the output
165-
math::Multiply<dsp::complex_t>::process(count, rtoc.out.writeBuf, pilotPLL.out.writeBuf, pilotPLL.out.writeBuf);
166-
convert::ComplexToReal::process(count, pilotPLL.out.writeBuf, rdsout);
167-
volk_32f_s32f_multiply_32f(rdsout, rdsout, 100.0, count);
168-
rdsOutCount = rdsResamp.process(count, rdsout, rdsout);
166+
// Translate to 0Hz
167+
xlator.process(count, rtoc.out.writeBuf, rtoc.out.writeBuf);
168+
169+
// Resample to the output samplerate
170+
rdsOutCount = rdsResamp.process(count, rtoc.out.writeBuf, rdsout);
169171
}
170172

171173
// Convert output back to real for further processing
172-
convert::ComplexToReal::process(count, rtoc.out.writeBuf, lmr);
174+
convert::ComplexToReal::process(count, lmrDelay.out.writeBuf, lmr);
173175

174176
// Amplify by 2x
175177
volk_32f_s32f_multiply_32f(lmr, lmr, 2.0f, count);
@@ -193,24 +195,11 @@ namespace dsp::demod {
193195
// Convert to complex
194196
rtoc.process(count, demod.out.writeBuf, rtoc.out.writeBuf);
195197

196-
// Filter out pilot and run through PLL
197-
pilotFir.process(count, rtoc.out.writeBuf, pilotFir.out.writeBuf);
198-
pilotPLL.process(count, pilotFir.out.writeBuf, pilotPLL.out.writeBuf);
199-
200-
// Delay
201-
lprDelay.process(count, demod.out.writeBuf, demod.out.writeBuf);
202-
lmrDelay.process(count, rtoc.out.writeBuf, rtoc.out.writeBuf);
203-
204-
// conjugate PLL output to down convert twice the L-R signal
205-
math::Conjugate::process(count, pilotPLL.out.writeBuf, pilotPLL.out.writeBuf);
206-
math::Multiply<dsp::complex_t>::process(count, rtoc.out.writeBuf, pilotPLL.out.writeBuf, rtoc.out.writeBuf);
207-
math::Multiply<dsp::complex_t>::process(count, rtoc.out.writeBuf, pilotPLL.out.writeBuf, rtoc.out.writeBuf);
208-
209-
// Since the PLL output is no longer needed after this, use it as the output
210-
math::Multiply<dsp::complex_t>::process(count, rtoc.out.writeBuf, pilotPLL.out.writeBuf, pilotPLL.out.writeBuf);
211-
convert::ComplexToReal::process(count, pilotPLL.out.writeBuf, rdsout);
212-
volk_32f_s32f_multiply_32f(rdsout, rdsout, 100.0, count);
213-
rdsOutCount = rdsResamp.process(count, rdsout, rdsout);
198+
// Translate to 0Hz
199+
xlator.process(count, rtoc.out.writeBuf, rtoc.out.writeBuf);
200+
201+
// Resample to the output samplerate
202+
rdsOutCount = rdsResamp.process(count, rtoc.out.writeBuf, rdsout);
214203
}
215204

216205
// Filter if needed
@@ -240,7 +229,7 @@ namespace dsp::demod {
240229
return count;
241230
}
242231

243-
stream<float> rdsOut;
232+
stream<complex_t> rdsOut;
244233

245234
protected:
246235
double _deviation;
@@ -253,13 +242,14 @@ namespace dsp::demod {
253242
tap<complex_t> pilotFirTaps;
254243
filter::FIR<complex_t, complex_t> pilotFir;
255244
convert::RealToComplex rtoc;
245+
channel::FrequencyXlator xlator;
256246
loop::PLL pilotPLL;
257247
math::Delay<float> lprDelay;
258248
math::Delay<complex_t> lmrDelay;
259249
tap<float> audioFirTaps;
260250
filter::FIR<float, float> arFir;
261251
filter::FIR<float, float> alFir;
262-
multirate::RationalResampler<float> rdsResamp;
252+
multirate::RationalResampler<dsp::complex_t> rdsResamp;
263253

264254
float* lmr;
265255
float* l;

core/src/dsp/demod/ssb.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ namespace dsp::demod {
110110
else if (_mode == Mode::LSB) {
111111
return -_bandwidth / 2.0;
112112
}
113-
else if (_mode == Mode::DSB) {
113+
else {
114114
return 0.0;
115115
}
116116
}

core/src/dsp/loop/phase_control_loop.h

+5
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ namespace dsp::loop {
6565
if constexpr(CLAMP_PHASE) { clampPhase(); }
6666
}
6767

68+
inline void advancePhase() {
69+
phase += freq;
70+
if constexpr(CLAMP_PHASE) { clampPhase(); }
71+
}
72+
6873
T freq;
6974
T phase;
7075

core/src/gui/widgets/waterfall.cpp

+30-3
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,33 @@ inline void printAndScale(double freq, char* buf) {
6262
}
6363
}
6464

65+
inline void doZoom(int offset, int width, int inSize, int outSize, float* in, float* out) {
66+
// NOTE: REMOVE THAT SHIT, IT'S JUST A HACKY FIX
67+
if (offset < 0) {
68+
offset = 0;
69+
}
70+
if (width > 524288) {
71+
width = 524288;
72+
}
73+
74+
float factor = (float)width / (float)outSize;
75+
float sFactor = ceilf(factor);
76+
float uFactor;
77+
float id = offset;
78+
float maxVal;
79+
int sId;
80+
for (int i = 0; i < outSize; i++) {
81+
maxVal = -INFINITY;
82+
sId = (int)id;
83+
uFactor = (sId + sFactor > inSize) ? sFactor - ((sId + sFactor) - inSize) : sFactor;
84+
for (int j = 0; j < uFactor; j++) {
85+
if (in[sId + j] > maxVal) { maxVal = in[sId + j]; }
86+
}
87+
out[i] = maxVal;
88+
id += factor;
89+
}
90+
}
91+
6592
namespace ImGui {
6693
WaterFall::WaterFall() {
6794
fftMin = -70.0;
@@ -586,7 +613,7 @@ namespace ImGui {
586613
for (int i = 0; i < count; i++) {
587614
drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize;
588615
drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
589-
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData);
616+
doZoom(drawDataStart, drawDataSize, rawFFTSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData);
590617
for (int j = 0; j < dataWidth; j++) {
591618
pixel = (std::clamp<float>(tempData[j], waterfallMin, waterfallMax) - waterfallMin) / dataRange;
592619
waterfallFb[(i * dataWidth) + j] = waterfallPallet[(int)(pixel * (WATERFALL_RESOLUTION - 1))];
@@ -867,7 +894,7 @@ namespace ImGui {
867894
int drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
868895

869896
if (waterfallVisible) {
870-
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
897+
doZoom(drawDataStart, drawDataSize, rawFFTSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
871898
memmove(&waterfallFb[dataWidth], waterfallFb, dataWidth * (waterfallHeight - 1) * sizeof(uint32_t));
872899
float pixel;
873900
float dataRange = waterfallMax - waterfallMin;
@@ -879,7 +906,7 @@ namespace ImGui {
879906
waterfallUpdate = true;
880907
}
881908
else {
882-
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs, latestFFT);
909+
doZoom(drawDataStart, drawDataSize, rawFFTSize, dataWidth, rawFFTs, latestFFT);
883910
fftLines = 1;
884911
}
885912

0 commit comments

Comments
 (0)