Sin 波 を作成してみる

Last Change:14-Jun-2016.
Author:qh73xe

ここでは、Haskell を使用し、サイン波を作成します。 これを wav ファイルに保存し、音を出してみることを目標とします。

  • 大前提として、全ての音声はサイン、コサインの組み合わせで表現できるとします。

サイン波を定義する

まずはサイン波を計算する関数を作成していきましょう。

注釈

サイン関数に関して

実際の所、 Haskell では sin 波を作成する関数は既に存在するのですが、 このサイトの目的は サウンドプログラミングを行いながら、 Haskell を学んでいくことにあるため、 基本的には既存のライブラリを使用するのではなく、 一から実装していきたいと思います。

ここで sin 波に関してですが、これは以下の数式で定義されています。

\[\begin{split}\sin(x) &= \sum_{n=0} a_n \\ a_0 &= x \\ a_{n+1} &= - \frac{x^2}{(2n+3)(2n+2)} a_n\end{split}\]

もしかすると上記式は以下のように記述した方が関数を考えやすいかもしれません。

\[\begin{split}\sin(x) &= \sum_{n=0} a_n(x) \\ a_0(x) &= x \\ a_{n+1}(x) &= - \frac{x^2}{(2n+3)(2n+2)} a_n\end{split}\]

上記式から、とりあえず、二つの関数を定義した方が良さようだということがわかります. sin(x) と a(x, n) ですね。

  • sum の上限を記述していませんが、ここではプログラム内で適当にきめることにします。

まずは簡単そうな sin 関数を考えてみます。 入出力を考えると、sin(x) は Double を受け取り Double を返します。

sin :: (Double) -> Double
sin(0.0) = 0.0
sin(x) = sum(a(x, 10))

一方 a(x, n) には入力が二つあり、それぞれ Double 型 と int 型です。 その結果 Double 型の出力を行いますね。

a :: (Double, Int) -> [Double]
a(x, n)
    | n == 0 = 0.0
    | otherwise = (x * x) / (2n + 3)(2n + 2) * a(x, n-1)