@@ -8,26 +8,26 @@ namespace MathCore.DSP.SDR;
88public 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>
0 commit comments