-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFaxMachine.cs
84 lines (57 loc) · 2.59 KB
/
FaxMachine.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
using NAudio.Wave;
using net.sictransit.wefax.extensions;
using Serilog;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Linq;
namespace net.sictransit.wefax
{
public class FaxMachine
{
private readonly int sampleRate;
private readonly int carrier;
private readonly int deviation;
private readonly int resolution;
private readonly float[] whiteBar;
public FaxMachine(int sampleRate = 8000, int carrier = 1600, int deviation = 400, int ioc = 576)
{
this.sampleRate = sampleRate;
this.carrier = carrier;
this.deviation = deviation;
resolution = (int)(Math.PI * ioc);
whiteBar = Enumerable.Repeat(1f, resolution / 20).ToArray();
}
public void Fax(string imageFilename, string audioFilename, BinaryCodedHeader bch)
{
Log.Information($"image input: {imageFilename}");
using var image = Image.Load<Rgb24>(imageFilename);
Log.Information($"original image: {image.Width}x{image.Height}");
var imageWidth = resolution - whiteBar.Length;
var scalingFactor = imageWidth / (float)image.Width;
image.Mutate(i => i.Resize((int)Math.Round(image.Width * scalingFactor), (int)Math.Round(image.Height * scalingFactor)));
Log.Information($"scaled image: {image.Width}x{image.Height}");
using var writer = new WaveFileWriter(audioFilename, new WaveFormat(sampleRate, 1));
Log.Information($"audio output: {audioFilename}");
var toneGenerator = new ToneGenerator(imageWidth, whiteBar, sampleRate, carrier, deviation);
var start = toneGenerator.GenerateStart();
writer.WriteSamples(start, 0, start.Length);
var phasing = toneGenerator.GeneratePhasing();
writer.WriteSamples(phasing, 0, phasing.Length);
if (!bch.IsEmpty)
{
var header = toneGenerator.GenerateBCH(bch);
writer.WriteSamples(header, 0, header.Length);
}
for (int y = 0; y < image.Height; y++)
{
var pixels = Enumerable.Range(0, image.Width).Select(x => image[x, y].GetBrightness() * 2f - 1).ToArray();
var samples = toneGenerator.GenerateLine(pixels);
writer.WriteSamples(samples, 0, samples.Length);
}
var stop = toneGenerator.GenerateStop();
writer.WriteSamples(stop, 0, stop.Length);
}
}
}