Skip to content

Commit d276d88

Browse files
committed
Переименование файлов в соответствии со смыслом алгоритмов
1 parent 09a614b commit d276d88

3 files changed

Lines changed: 47 additions & 49 deletions

File tree

MathCore.DSP/Samples/Extensions/SampleSI16Ex.cs renamed to MathCore.DSP/Samples/Extensions/SampleSI16PhaseModulationEx.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace MathCore.DSP.Samples.Extensions;
44

5-
public static class SampleSI16Ex
5+
public static class SampleSI16PhaseModulationEx
66
{
77
/// <summary>Фазовая демодуляция радиосигнала</summary>
88
/// <param name="samples">Последовательность отсчётов квадратурного радиосигнала</param>
@@ -64,7 +64,6 @@ public static SampleSI16[] PhaseModulation(this ReadOnlySpan<float> data, double
6464

6565
var result = new SampleSI16[data.Length];
6666
var dt = 1.0 / fd;
67-
var omega0 = 2.0 * Math.PI * f0;
6867
var accumulated_phase = 0.0;
6968

7069
for (var i = 0; i < data.Length; i++)
@@ -78,8 +77,7 @@ public static SampleSI16[] PhaseModulation(this ReadOnlySpan<float> data, double
7877

7978
// Генерируем квадратурный сигнал: I = A*cos(φ), Q = A*sin(φ)
8079
#if NET8_0_OR_GREATER
81-
var cos_phase = MathF.Cos((float)accumulated_phase);
82-
var sin_phase = MathF.Sin((float)accumulated_phase);
80+
var (sin_phase, cos_phase) = MathF.SinCos((float)accumulated_phase);
8381
#else
8482
var cos_phase = (float)Math.Cos(accumulated_phase);
8583
var sin_phase = (float)Math.Sin(accumulated_phase);
@@ -89,7 +87,7 @@ public static SampleSI16[] PhaseModulation(this ReadOnlySpan<float> data, double
8987
var i_sample = ClampToSByte(amplitude * cos_phase);
9088
var q_sample = ClampToSByte(amplitude * sin_phase);
9189

92-
result[i] = new SampleSI16(i_sample, q_sample);
90+
result[i] = new(i_sample, q_sample);
9391
}
9492

9593
return result;

Tests/MathCore.DSP.Tests/Samples/Extensions/SampleSI16ExTests.cs renamed to Tests/MathCore.DSP.Tests/Samples/Extensions/SampleSI16PhaseModulationExTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace MathCore.DSP.Tests.Samples.Extensions;
55

66
[TestClass]
7-
public class SampleSI16ExTests
7+
public class SampleSI16PhaseModulationExTests
88
{
99
/// <summary>Тест фазовой демодуляции для пустого массива</summary>
1010
[TestMethod]

Tests/MathCore.DSP.Tests/Samples/SampleSI16ExTests.cs renamed to Tests/MathCore.DSP.Tests/Samples/SampleSI16PhaseModulationExTests.cs

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace MathCore.DSP.Tests.Samples;
55

66
[TestClass]
7-
public class SampleSI16ExTests
7+
public class SampleSI16PhaseModulationExTests
88
{
99
/// <summary>Тест фазовой демодуляции для пустого массива</summary>
1010
[TestMethod]
@@ -52,7 +52,7 @@ public void PhaseDemodulation_ConstantSignal_ReturnsNearZeros()
5252
new(100, 0),
5353
new(100, 0)
5454
}.AsSpan();
55-
55+
5656
const double f0 = 1000.0;
5757
const double fd = 48000.0;
5858

@@ -62,12 +62,12 @@ public void PhaseDemodulation_ConstantSignal_ReturnsNearZeros()
6262
// Assert
6363
Assert.AreEqual(5, result.Length);
6464
Assert.AreEqual(0f, result[0]); // Первый всегда 0
65-
65+
6666
// Для постоянного сигнала мгновенная частота должна быть близка к нулю
6767
// после вычитания центральной частоты результат должен быть близок к -f0
6868
for (var i = 1; i < result.Length; i++)
6969
{
70-
Assert.IsTrue(Math.Abs(result[i] + f0) < 50,
70+
Assert.IsTrue(Math.Abs(result[i] + f0) < 50,
7171
$"Sample {i}: expected ~{-f0}, got {result[i]}");
7272
}
7373
}
@@ -81,16 +81,16 @@ public void PhaseDemodulation_SinusoidalSignal_ReturnsExpectedFrequency()
8181
const double f0 = 1000.0; // Центральная частота
8282
const double f_signal = 1500.0; // Частота сигнала
8383
const int samples_count = 200;
84-
84+
8585
var samples = new SampleSI16[samples_count];
8686
var dt = 1.0 / fd;
87-
87+
8888
for (var i = 0; i < samples_count; i++)
8989
{
9090
var t = i * dt;
9191
var angle = 2.0 * Math.PI * f_signal * t;
9292
var amplitude = 100.0;
93-
93+
9494
samples[i] = new SampleSI16(
9595
(sbyte)(amplitude * Math.Cos(angle)),
9696
(sbyte)(amplitude * Math.Sin(angle))
@@ -103,19 +103,19 @@ public void PhaseDemodulation_SinusoidalSignal_ReturnsExpectedFrequency()
103103
// Assert
104104
Assert.AreEqual(samples_count, result.Length);
105105
Assert.AreEqual(0f, result[0]); // Первый всегда 0
106-
106+
107107
// Проверяем, что результат близок к ожидаемой частоте (f_signal - f0)
108108
var expected_frequency = f_signal - f0;
109109
var tolerance = 100.0; // Допуск в Гц
110-
110+
111111
// Проверяем стабильную часть сигнала (пропускаем начальные образцы)
112112
var stable_samples = 0;
113113
for (var i = 20; i < result.Length - 20; i++) // Пропускаем края для стабилизации
114114
{
115115
if (Math.Abs(result[i] - expected_frequency) < tolerance)
116116
stable_samples++;
117117
}
118-
118+
119119
// Проверяем, что большинство образцов дает правильную частоту
120120
var expected_stable_count = (result.Length - 40) * 0.8; // 80% образцов должны быть стабильными
121121
Assert.IsTrue(stable_samples > expected_stable_count,
@@ -130,7 +130,7 @@ public void PhaseDemodulation_OptimizedPerformance_BetterThanOldVersion()
130130
const int samples_count = 1_000_000; // Увеличиваем размер для лучшего измерения
131131
var samples = new SampleSI16[samples_count];
132132
var random = new Random(42); // Фиксированное семя для воспроизводимости
133-
133+
134134
for (var i = 0; i < samples_count; i++)
135135
{
136136
samples[i] = new SampleSI16(
@@ -150,17 +150,17 @@ public void PhaseDemodulation_OptimizedPerformance_BetterThanOldVersion()
150150
var result = samples.AsSpan().PhaseDemodulation(f0, fd);
151151
stopwatch.Stop();
152152
times.Add(stopwatch.ElapsedMilliseconds);
153-
153+
154154
// Проверяем корректность результата
155155
Assert.AreEqual(samples_count, result.Length);
156156
}
157157

158158
var average_time = times.Average();
159-
159+
160160
// Assert - должно быть быстрее чем 1000 мс для 1M образцов
161-
Assert.IsTrue(average_time < 1000,
161+
Assert.IsTrue(average_time < 1000,
162162
$"Optimized demodulation took {average_time:F1} ms on average, expected < 1000 ms");
163-
163+
164164
Console.WriteLine($"Оптимизированная фазовая демодуляция {samples_count} образцов:");
165165
Console.WriteLine($"Среднее время: {average_time:F1} мс");
166166
Console.WriteLine($"Производительность: {samples_count / average_time / 1000:F1} млн. образцов/сек");
@@ -173,7 +173,7 @@ public void PhaseDemodulation_PhaseUnwrap_WorksCorrectly()
173173
// Arrange - создаем сигнал с плавно изменяющейся фазой, но с перескоками ±2π
174174
const double fd = 1000.0;
175175
const double f0 = 0.0; // Нулевая центральная частота для простоты
176-
176+
177177
var samples = new SampleSI16[]
178178
{
179179
new(100, 0), // фаза ≈ 0
@@ -192,11 +192,11 @@ public void PhaseDemodulation_PhaseUnwrap_WorksCorrectly()
192192
// Assert
193193
Assert.AreEqual(samples.Length, result.Length);
194194
Assert.AreEqual(0f, result[0]); // Первый всегда 0
195-
195+
196196
// Проверяем, что результаты имеют разумные значения без больших скачков
197197
for (var i = 1; i < result.Length; i++)
198198
{
199-
Assert.IsTrue(Math.Abs(result[i]) < 1000,
199+
Assert.IsTrue(Math.Abs(result[i]) < 1000,
200200
$"Sample {i}: frequency {result[i]} Hz seems too high");
201201
}
202202
}
@@ -208,18 +208,18 @@ public void PhaseDemodulation_OptimizedVsNaive_SameAccuracy()
208208
// Arrange - создаем чистый синусоидальный сигнал
209209
const double fd = 48000.0;
210210
const double f0 = 1000.0;
211-
const double f_signal = 1200.0;
211+
const double f_signal = 1200.0;
212212
const int samples_count = 100;
213-
213+
214214
var samples = new SampleSI16[samples_count];
215215
var dt = 1.0 / fd;
216-
216+
217217
for (var i = 0; i < samples_count; i++)
218218
{
219219
var t = i * dt;
220220
var angle = 2.0 * Math.PI * f_signal * t;
221221
var amplitude = 120.0; // Используем почти максимальную амплитуду
222-
222+
223223
samples[i] = new SampleSI16(
224224
(sbyte)(amplitude * Math.Cos(angle)),
225225
(sbyte)(amplitude * Math.Sin(angle))
@@ -232,19 +232,19 @@ public void PhaseDemodulation_OptimizedVsNaive_SameAccuracy()
232232
// Assert - проверяем точность на стабильной части
233233
var expected_frequency = f_signal - f0;
234234
var errors = new List<float>();
235-
235+
236236
for (var i = 10; i < optimized_result.Length - 10; i++)
237237
{
238238
var error = (float)Math.Abs(optimized_result[i] - expected_frequency);
239239
errors.Add(error);
240240
}
241-
241+
242242
var average_error = errors.Average();
243243
var max_error = errors.Max();
244-
244+
245245
Assert.IsTrue(average_error < 50, $"Average error {average_error:F1} Hz too high");
246246
Assert.IsTrue(max_error < 100, $"Max error {max_error:F1} Hz too high");
247-
247+
248248
Console.WriteLine($"Точность оптимизированного алгоритма:");
249249
Console.WriteLine($"Средняя ошибка: {average_error:F1} Гц");
250250
Console.WriteLine($"Максимальная ошибка: {max_error:F1} Гц");
@@ -283,12 +283,12 @@ public void PhaseModulation_ConstantFrequency_GeneratesCorrectSignal()
283283

284284
// Assert
285285
Assert.AreEqual(data.Length, result.Length);
286-
286+
287287
// Проверяем, что амплитуда близка к заданной
288288
for (var i = 0; i < result.Length; i++)
289289
{
290290
var sample_amplitude = Math.Sqrt(result[i].I * result[i].I + result[i].Q * result[i].Q);
291-
Assert.IsTrue(Math.Abs(sample_amplitude - amplitude) < 5,
291+
Assert.IsTrue(Math.Abs(sample_amplitude - amplitude) < 5,
292292
$"Sample {i}: amplitude {sample_amplitude:F1} too far from expected {amplitude}");
293293
}
294294
}
@@ -298,8 +298,8 @@ public void PhaseModulation_ConstantFrequency_GeneratesCorrectSignal()
298298
public void PhaseModulation_RoundTrip_PreservesData()
299299
{
300300
// Arrange - создаем тестовые данные с различными частотами
301-
var original_data = new float[]
302-
{
301+
var original_data = new float[]
302+
{
303303
0f, // Без отклонения
304304
100f, // +100 Гц
305305
-200f, // -200 Гц
@@ -308,21 +308,21 @@ public void PhaseModulation_RoundTrip_PreservesData()
308308
0f, // Возврат к центральной
309309
50f, // Небольшое отклонение
310310
};
311-
311+
312312
const double f0 = 2000.0;
313313
const double fd = 48000.0;
314314
const float amplitude = 120f;
315315

316316
// Act - модуляция
317317
var modulated = original_data.AsSpan().PhaseModulation(f0, fd, amplitude);
318-
318+
319319
// Демодуляция
320320
var demodulated = modulated.AsSpan().PhaseDemodulation(f0, fd);
321321

322322
// Assert
323323
Assert.AreEqual(original_data.Length, demodulated.Length);
324324
Assert.AreEqual(0f, demodulated[0]); // Первый отсчёт всегда 0
325-
325+
326326
// Проверяем восстановление данных (пропускаем первый отсчёт и края)
327327
const float tolerance = 50f; // Допуск в Гц
328328
for (var i = 2; i < demodulated.Length - 1; i++) // Пропускаем края из-за переходных процессов
@@ -345,26 +345,26 @@ public void PhaseModulation_WithInitialPhase_MaintainsPhaseContinuity()
345345

346346
// Act - первый блок
347347
var (samples1, final_phase1) = data1.AsSpan().PhaseModulation(f0, fd, 0.0);
348-
348+
349349
// Второй блок с продолжением фазы
350350
var (samples2, final_phase2) = data2.AsSpan().PhaseModulation(f0, fd, final_phase1);
351351

352352
// Assert
353353
Assert.AreEqual(data1.Length, samples1.Length);
354354
Assert.AreEqual(data2.Length, samples2.Length);
355-
355+
356356
// Проверяем непрерывность фазы на стыке блоков
357357
var last_sample = samples1[^1];
358358
var first_sample = samples2[0];
359-
359+
360360
var last_phase = Math.Atan2(last_sample.Q, last_sample.I);
361361
var first_phase = Math.Atan2(first_sample.Q, first_sample.I);
362-
362+
363363
// Разность фаз должна быть небольшой (с учётом возможного перескока через ±π)
364364
var phase_diff = Math.Abs(first_phase - last_phase);
365365
if (phase_diff > Math.PI) phase_diff = 2 * Math.PI - phase_diff;
366-
367-
Assert.IsTrue(phase_diff < 0.5,
366+
367+
Assert.IsTrue(phase_diff < 0.5,
368368
$"Phase discontinuity too large: {phase_diff:F3} rad");
369369
}
370370

@@ -376,10 +376,10 @@ public void PhaseModulation_Performance_CompletesQuickly()
376376
const int data_count = 1_000_000;
377377
var data = new float[data_count];
378378
var random = new Random(42);
379-
379+
380380
for (var i = 0; i < data_count; i++)
381381
data[i] = (float)(random.NextDouble() * 1000 - 500); // ±500 Гц
382-
382+
383383
const double f0 = 2400.0;
384384
const double fd = 48000.0;
385385

@@ -390,9 +390,9 @@ public void PhaseModulation_Performance_CompletesQuickly()
390390

391391
// Assert
392392
Assert.AreEqual(data_count, result.Length);
393-
Assert.IsTrue(stopwatch.ElapsedMilliseconds < 500,
393+
Assert.IsTrue(stopwatch.ElapsedMilliseconds < 500,
394394
$"Modulation took {stopwatch.ElapsedMilliseconds} ms, expected < 500 ms");
395-
395+
396396
Console.WriteLine($"Фазовая модуляция {data_count} образцов заняла {stopwatch.ElapsedMilliseconds} мс");
397397
Console.WriteLine($"Производительность: {data_count / (double)stopwatch.ElapsedMilliseconds / 1000:F1} млн. образцов/сек");
398398
}

0 commit comments

Comments
 (0)