概要
paiza.ioでelixirやってみた。
練習問題やってみた。
練習問題
sin波を、AM変調して、AM復調して、元に戻せ。
ソースは、220Hzの正弦波。
搬送波は、3000Hz
サンプリングレートは、8000
サンプルコード
defmodule Out2 do
use Agent
def start_link() do
Agent.start_link(fn ->
0
end, name: __MODULE__)
end
def get() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def put(o) do
Agent.update(__MODULE__, fn v ->
o
end)
end
end
defmodule Out1 do
use Agent
def start_link() do
Agent.start_link(fn ->
0
end, name: __MODULE__)
end
def get() do
Agent.get(__MODULE__, fn v ->
v
end)
end
def put(o) do
Agent.update(__MODULE__, fn v ->
o
end)
end
end
defmodule Main do
require Logger
def vi(v) do
v
|> Enum.with_index()
|> Enum.map(fn {x, t} ->
x * :math.cos(t / 8000 * 2 * :math.pi * 3000);
end)
end
def vq(v) do
v
|> Enum.with_index()
|> Enum.map(fn {x, t} ->
x * :math.sin(t / 8000 * 2 * :math.pi * 3000);
end)
end
def vin(v) do
v
|> Enum.with_index()
|> Enum.map(fn {x, t} ->
:math.sin(t / 8000 * 2 * :math.pi * 220);
end)
end
def vam(v) do
v
|> Enum.with_index()
|> Enum.map(fn {x, t} ->
(0.6 * :math.sin(t / 8000 * 2 * :math.pi * 220) + 1.0) * :math.sin(t / 8000 * 2 * :math.pi * 3000) * 2 - 1;
end)
end
def lpf(v) do
samplerate = 8000.0
freq = 300.0
q = 1.0
omega = 2.0 * :math.pi * freq / samplerate
alpha = :math.sin(omega) / (2.0 * q)
a0 = 1.0 + alpha
a1 = -2.0 * :math.cos(omega)
a2 = 1.0 - alpha
b0 = (1.0 - :math.cos(omega)) / 2.0
b1 = 1.0 - :math.cos(omega)
b2 = (1.0 - :math.cos(omega)) / 2.0
in1 = 0
in2 = 0
for n <- 0..299 do
x = Enum.at(v, n)
in2 = Enum.at(v, n - 2)
in1 = Enum.at(v, n - 1)
out2 = Out2.get
out1 = Out1.get
v = b0 / a0 * x + b1 / a0 * in1 + b2 / a0 * in2 - a1 / a0 * out1 - a2 / a0 * out2
Out2.put(out1)
Out1.put(v)
v
end
end
def main do
Out2.start_link
Out1.start_link
IO.puts """
<html><head></head><body>
<canvas id="canvas" width="300" height="300"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
function draw(data, n) {
var hcenter = n * 100 + 50;
ctx.strokeStyle = "#f0f";
ctx.lineWidth = 2;
ctx.moveTo(0, hcenter);
for (var i = 1; i < canvas.width; i++)
{
ctx.lineTo(i, data[i] * 15 + hcenter);
}
ctx.stroke();
}
var src = [
"""
src = List.duplicate(0, 300)
src = vin(src)
Enum.map(src, fn x ->
IO.write(x)
IO.write(",")
end)
IO.puts """
];
var dst = [
"""
dis = List.duplicate(0, 300)
dis = vam(dis)
Enum.map(dis, fn x ->
IO.write(x)
IO.write(",")
end)
IO.puts """
];
var dec = [
"""
i = vi(dis)
q = vq(dis)
i2 = lpf(i)
q2 = lpf(q)
for n <- 0..299 do
x = :math.sqrt(Enum.at(i2, n) * Enum.at(i2, n) + Enum.at(q2, n) * Enum.at(q2, n)) * 2 - 4;
IO.write(x)
IO.write(",")
end
IO.puts """
];
draw(src, 0);
draw(dst, 1);
draw(dec, 2);
</script></body></html>
"""
end
end
Main.main
実行結果
成果物
以上。