-
Notifications
You must be signed in to change notification settings - Fork 2
/
ToneGenerator.cs
111 lines (83 loc) · 3.54 KB
/
ToneGenerator.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
using Serilog;
using System;
using System.Linq;
namespace net.sictransit.wefax
{
public class ToneGenerator
{
private readonly int imageWidth;
private readonly float[] whiteBar;
private readonly int carrier;
private readonly int deviation;
private readonly int lineLength;
private readonly double dt;
private double time = 0;
public ToneGenerator(int imageWidth, float[] whiteBar, int sampleRate, int carrier, int deviation)
{
this.imageWidth = imageWidth;
this.whiteBar = whiteBar;
this.carrier = carrier;
this.deviation = deviation;
lineLength = sampleRate / 2;
dt = Math.PI * 2 / sampleRate;
}
public float[] GeneratePhasing()
{
var modulation = Enumerable.Range(0, imageWidth).Select(_ => -1f).ToArray();
return Enumerable.Range(0, 20 * 2).Select(_ => GenerateLine(modulation)).SelectMany(x => x).ToArray();
}
public float[] GenerateStart()
{
return GenerateSquareWave(300, 5);
}
public float[] GenerateStop()
{
return GenerateSquareWave(450, 5);
}
public float[] GenerateBCH(BinaryCodedHeader bch, bool debug = false)
{
Log.Information($"encoding BCH: [{bch.Text}]");
if (Log.IsEnabled(Serilog.Events.LogEventLevel.Debug))
{
var binary = bch.Binary.ToArray();
for (int i = 0; i < bch.Text.Length; i++)
{
var chunk = new string(binary.Skip(8 * i).Take(8).Select(x => x == 1 ? '1' : '0').ToArray());
var b = Convert.ToByte(chunk, 2);
Log.Debug($"decoded BCH: {(char)b} ({string.Concat(chunk.Select(x => x.ToString()).ToArray())})");
}
}
var bitLength = 4;
var one = Enumerable.Repeat(1f, bitLength).ToArray();
var zero = Enumerable.Repeat(-1f, bitLength).ToArray();
var bin = debug
? Enumerable.Range(0, bch.Binary.Count()).Select(x => x / 8 % 2 == 0 ? zero : one).SelectMany(x => x).ToArray()
: bch.Binary.Select(x => x == 1 ? one : zero).SelectMany(x => x).ToArray();
var padding = new float[imageWidth - bin.Length];
return Enumerable.Range(0, bitLength).Select(_ => GenerateLine(bin.Concat(padding).ToArray())).SelectMany(x => x).ToArray();
}
public float[] GenerateLine(float[] pixels = null, bool bar = true)
{
if (pixels == null)
{
pixels = Array.Empty<float>();
}
var modulation = bar ? whiteBar.Concat(pixels).ToArray() : pixels;
var interpolationFactor = (double)modulation.Length / lineLength;
var line = new float[lineLength];
for (int i = 0; i < lineLength; i++)
{
var pixel = (int)(i * interpolationFactor);
var frequency = carrier + deviation * modulation[pixel];
time += dt * frequency;
line[i] = (float)Math.Sin(time);
}
return line;
}
private float[] GenerateSquareWave(int frequency, int duration)
{
var modulation = Enumerable.Range(0, frequency).Select(x => x % 2 == 0 ? -1f : 1f).ToArray();
return Enumerable.Range(0, duration * 2).Select(_ => GenerateLine(modulation, false)).SelectMany(x => x).ToArray();
}
}
}