Skip to content

Commit f3a35dd

Browse files
committed
Исправлены названия параметров и методов для единообразия в SdrSignalProcessing: заменены RawIq на IQ и Iq8 на IQ8 в комментариях и коде
1 parent 3df5965 commit f3a35dd

2 files changed

Lines changed: 37 additions & 36 deletions

File tree

MathCore.DSP/SDR/SdrSignalProcessing.cs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,26 @@ namespace MathCore.DSP.SDR;
88
public static class SdrSignalProcessing
99
{
1010
/// <summary>Рассчитать базовые метрики interleaved IQ-потока int8</summary>
11-
/// <param name="RawIq">Байтовый буфер формата I,Q,I,Q</param>
11+
/// <param name="IQ">Байтовый буфер формата I,Q,I,Q</param>
1212
/// <returns>Кортеж средних, RMS, доли клиппинга и средней мощности</returns>
1313
/// <exception cref="ArgumentNullException">Буфер исходных данных не задан</exception>
1414
/// <exception cref="ArgumentException">Длина буфера не кратна двум</exception>
1515
/// <remarks>
1616
/// Пример использования:
1717
/// <code><![CDATA[
18-
/// var metrics = SdrSignalProcessing.ComputeIq8Metrics(raw_iq);
18+
/// var metrics = SdrSignalProcessing.ComputeIQ8Metrics(raw_iq);
1919
/// Console.WriteLine($"Mean I={metrics.mean_i:F4}, Mean Q={metrics.mean_q:F4}");
2020
/// ]]></code>
2121
/// </remarks>
22-
public static (double mean_i, double mean_q, double rms_i, double rms_q, double clip_ratio, double avg_power) ComputeIq8Metrics(byte[] RawIq)
22+
public static (double mean_i, double mean_q, double rms_i, double rms_q, double clip_ratio, double avg_power) ComputeIQ8Metrics(byte[] IQ)
2323
{
24-
ArgumentNullException.ThrowIfNull(RawIq);
24+
ArgumentNullException.ThrowIfNull(IQ);
2525

26-
if ((RawIq.Length & 1) != 0)
27-
throw new ArgumentException("Размер массива IQ должен быть кратен двум", nameof(RawIq));
26+
if ((IQ.Length & 1) != 0)
27+
throw new ArgumentException("Размер массива IQ должен быть кратен двум", nameof(IQ));
2828

29-
if (RawIq.Length == 0)
30-
return (0, 0, 0, 0, 0, 0);
29+
if (IQ.Length == 0)
30+
return default;
3131

3232
var i_sum = 0d;
3333
var q_sum = 0d;
@@ -36,11 +36,11 @@ public static (double mean_i, double mean_q, double rms_i, double rms_q, double
3636
var pwr_sum = 0d;
3737
var clip_count = 0;
3838

39-
var count = RawIq.Length / 2;
40-
for (var index = 0; index < RawIq.Length; index += 2)
39+
var count = IQ.Length / 2;
40+
for (var index = 0; index < IQ.Length; index += 2)
4141
{
42-
var i_value = unchecked((sbyte)RawIq[index]);
43-
var q_value = unchecked((sbyte)RawIq[index + 1]);
42+
var i_value = unchecked((sbyte)IQ[index]);
43+
var q_value = unchecked((sbyte)IQ[index + 1]);
4444

4545
i_sum += i_value;
4646
q_sum += q_value;
@@ -71,11 +71,11 @@ public static (double mean_i, double mean_q, double rms_i, double rms_q, double
7171
/// <remarks>
7272
/// Пример использования:
7373
/// <code><![CDATA[
74-
/// var dc_metrics = SdrSignalProcessing.ComputeComplexDcMetrics(iq_after_dc);
74+
/// var dc_metrics = SdrSignalProcessing.ComputeComplexDCMetrics(iq_after_dc);
7575
/// Console.WriteLine($"Pdc={dc_metrics.dc_power:E6}");
7676
/// ]]></code>
7777
/// </remarks>
78-
public static (double mean_i, double mean_q, double dc_power) ComputeComplexDcMetrics(ComplexN[] Samples)
78+
public static (double mean_i, double mean_q, double dc_power) ComputeComplexDCMetrics(ComplexN[] Samples)
7979
{
8080
ArgumentNullException.ThrowIfNull(Samples);
8181

@@ -108,7 +108,7 @@ public static (double mean_i, double mean_q, double dc_power) ComputeComplexDcMe
108108
public static double ToDb(double Ratio) => 10 * Math.Log10(Math.Max(Ratio, 1e-18));
109109

110110
/// <summary>Убрать DC-компоненту из interleaved IQ-потока int8</summary>
111-
/// <param name="RawIq">Байтовый буфер формата I,Q,I,Q</param>
111+
/// <param name="IQ">Байтовый буфер формата I,Q,I,Q</param>
112112
/// <param name="Alpha">Коэффициент сглаживания экспоненциальной оценки среднего в диапазоне (0;1]</param>
113113
/// <returns>Массив комплексных IQ-отсчётов после подавления DC</returns>
114114
/// <exception cref="ArgumentNullException">Буфер исходных данных не задан</exception>
@@ -117,29 +117,29 @@ public static (double mean_i, double mean_q, double dc_power) ComputeComplexDcMe
117117
/// <remarks>
118118
/// Пример использования:
119119
/// <code><![CDATA[
120-
/// var iq_after_dc = SdrSignalProcessing.RemoveDcFromInterleavedIq8(raw_iq, Alpha: 0.0025);
120+
/// var iq_after_dc = SdrSignalProcessing.RemoveDcFromInterleavedIQ8(raw_iq, Alpha: 0.0025);
121121
/// ]]></code>
122122
/// </remarks>
123-
public static ComplexN[] RemoveDcFromInterleavedIq8(byte[] RawIq, double Alpha)
123+
public static ComplexN[] RemoveDcFromInterleavedIQ8(byte[] IQ, double Alpha)
124124
{
125-
ArgumentNullException.ThrowIfNull(RawIq);
125+
ArgumentNullException.ThrowIfNull(IQ);
126126

127127
if (Alpha <= 0 || Alpha > 1)
128128
throw new ArgumentOutOfRangeException(nameof(Alpha), Alpha, "Коэффициент сглаживания должен быть в диапазоне (0;1]");
129129

130-
if ((RawIq.Length & 1) != 0)
131-
throw new ArgumentException("Размер массива IQ должен быть кратен двум", nameof(RawIq));
130+
if ((IQ.Length & 1) != 0)
131+
throw new ArgumentException("Размер массива IQ должен быть кратен двум", nameof(IQ));
132132

133-
var count = RawIq.Length / 2;
133+
var count = IQ.Length / 2;
134134
var result = new ComplexN[count];
135135

136136
var mean_i = 0d;
137137
var mean_q = 0d;
138138

139139
for (var index = 0; index < count; index++)
140140
{
141-
var i_value = unchecked((sbyte)RawIq[2 * index]);
142-
var q_value = unchecked((sbyte)RawIq[2 * index + 1]);
141+
var i_value = unchecked((sbyte)IQ[2 * index]);
142+
var q_value = unchecked((sbyte)IQ[2 * index + 1]);
143143

144144
var i_d = (double)i_value;
145145
var q_d = (double)q_value;
@@ -221,11 +221,9 @@ public static double EstimateChannelPower(ReadOnlySpan<ComplexN> Source, double
221221
for (var index = 0; index < Source.Length; index++)
222222
{
223223
var phase = phase_step * index;
224-
var lo_i = Math.Cos(phase);
225-
var lo_q = Math.Sin(phase);
224+
var (lo_q, lo_i) = Math.SinCos(phase);
226225

227-
var sample_i = Source[index].Real;
228-
var sample_q = Source[index].Imaginary;
226+
var (sample_i, sample_q) = (Source[index].Real, Source[index].Imaginary);
229227

230228
var mix_i = sample_i * lo_i - sample_q * lo_q;
231229
var mix_q = sample_i * lo_q + sample_q * lo_i;
@@ -275,16 +273,18 @@ public static double[] DesignLowPassFirBlackman(double SampleRateHz, double Pass
275273
var cutoff_hz = PassbandHz + TransitionHz * 0.5;
276274
var fc = cutoff_hz / SampleRateHz;
277275

276+
var w = 2 * Math.PI / (TapCount - 1);
277+
var w_fc = 2 * Math.PI * fc;
278278
for (var n = 0; n < TapCount; n++)
279279
{
280280
var k = n - middle;
281281
var sinc = k == 0
282282
? 2 * fc
283-
: Math.Sin(2 * Math.PI * fc * k) / (Math.PI * k);
283+
: Math.Sin(w_fc * k) / (Math.PI * k);
284284

285285
var window = 0.42
286-
- 0.5 * Math.Cos(2 * Math.PI * n / (TapCount - 1))
287-
+ 0.08 * Math.Cos(4 * Math.PI * n / (TapCount - 1));
286+
- 0.5 * Math.Cos(w * n)
287+
+ 0.08 * Math.Cos(2 * w * n);
288288

289289
taps[n] = sinc * window;
290290
}
@@ -343,7 +343,7 @@ public static ComplexN[] LowPassDecimateComplex(ComplexN[] Source, double[] Taps
343343
output.Add(new(i_acc, q_acc));
344344
}
345345

346-
return output.ToArray();
346+
return [..output];
347347
}
348348

349349
/// <summary>Выполнить рациональный ресемплинг комплексного сигнала по windowed-sinc ядру</summary>
@@ -389,6 +389,7 @@ public static ComplexN[] ResampleRationalSinc(ComplexN[] Source, int Interpolati
389389
var q_acc = 0d;
390390
var w_sum = 0d;
391391

392+
var w = Math.PI / (HalfTaps + 1);
392393
for (var tap = -HalfTaps; tap <= HalfTaps; tap++)
393394
{
394395
var src_index = src_center + tap;
@@ -400,7 +401,7 @@ public static ComplexN[] ResampleRationalSinc(ComplexN[] Source, int Interpolati
400401
? 1d
401402
: Math.Sin(Math.PI * x) / (Math.PI * x);
402403

403-
var window = 0.54 + 0.46 * Math.Cos(Math.PI * x / (HalfTaps + 1));
404+
var window = 0.54 + 0.46 * Math.Cos(w * x);
404405
var weight = sinc * window;
405406

406407
var sample = Source[src_index];
@@ -513,7 +514,7 @@ public static double[] LowPassDecimateReal(double[] Source, double[] Taps, int D
513514
output.Add(acc);
514515
}
515516

516-
return output.ToArray();
517+
return [..output];
517518
}
518519

519520
/// <summary>Рассчитать RMS вещественного сигнала</summary>

Tests/ConsoleTest/Program.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
vga_gain_db,
3636
out var rx_statistics);
3737

38-
var stage1_metrics = SdrSignalProcessing.ComputeIq8Metrics(captured_data); // Базовые метрики качества входного тракта
38+
var stage1_metrics = SdrSignalProcessing.ComputeIQ8Metrics(captured_data); // Базовые метрики качества входного тракта
3939

4040
Console.WriteLine($"Получено байт: {captured_data.Length}");
4141
Console.WriteLine($"Получено IQ-отсчётов: {captured_data.Length / 2}");
@@ -52,10 +52,10 @@
5252
Console.WriteLine();
5353
Console.WriteLine("Этап 2. Подавление DC-пика");
5454

55-
var iq_after_dc = SdrSignalProcessing.RemoveDcFromInterleavedIq8(captured_data, Alpha: 0.0025); // Подавляем пик на нулевой частоте
55+
var iq_after_dc = SdrSignalProcessing.RemoveDcFromInterleavedIQ8(captured_data, Alpha: 0.0025); // Подавляем пик на нулевой частоте
5656

5757
var stage2_before = (mean_i: stage1_metrics.mean_i, mean_q: stage1_metrics.mean_q, dc_power: stage1_metrics.mean_i * stage1_metrics.mean_i + stage1_metrics.mean_q * stage1_metrics.mean_q);
58-
var stage2_after = SdrSignalProcessing.ComputeComplexDcMetrics(iq_after_dc);
58+
var stage2_after = SdrSignalProcessing.ComputeComplexDCMetrics(iq_after_dc);
5959

6060
Console.WriteLine($"DC до: I={stage2_before.mean_i:F5}, Q={stage2_before.mean_q:F5}, Pdc={stage2_before.dc_power:F6}");
6161
Console.WriteLine($"DC после: I={stage2_after.mean_i:F5}, Q={stage2_after.mean_q:F5}, Pdc={stage2_after.dc_power:F6}");

0 commit comments

Comments
 (0)