微分音律版フィボナッチミュージック

Beepを使って作りました。Windows限定。コマンドライン引数で音律(12音平均律だったら12)と、いくつの音を使うか(これで曲が決まります)を指定できます。
24音平均律の25がいい感じの曲になっています。
一応実行形式も用意しました。ダウンロードはこちらから。

-- -*- compile-command: "ghc -W -ffi -o fib2.exe fib2.hs" -*-
module Main (main) where

import Control.Concurrent (threadDelay)
import System.IO
import System (getArgs)
import System.Win32 (UINT, BOOL)

foreign import stdcall unsafe "Beep" cBeep :: UINT -> UINT -> IO BOOL

freqs :: Double -> Int -> [Double]
freqs hz k = [hz * h(i) | i <- [0 ..]]
    where
      h :: Int -> Double
      h i = 2.0 ** (fromIntegral i / fromIntegral k)

-- ref. <http://haskell.g.hatena.ne.jp/harg/20060822/1156262334>
fastFib :: Integer -> Integer
fastFib = fst . fibPair
    where
      fibStep :: (Integer, Integer) -> (Integer, Integer)
      fibStep (u, v) = (v, u+v)

      fibPair :: Integer -> (Integer, Integer)
      fibPair n
        | n == 0    = (0, 1)
        | otherwise = fibStep (fibPair (n-1))

main :: IO ()
main = do
  args <- getArgs
  let k = if (length args < 1) then 12 else read $ args !! 0
      l = if (length args < 2) then 19 else read $ args !! 1
  mapM_ (f k l) [fastFib(n) | n <- [1 ..]]
    where
      f k l x = do
        let x' = fromInteger $ x `mod` l
            hz = round $ freqs 220.0 k !! x'
        print (hz, x)
        hFlush stdout
        cBeep hz 200
        threadDelay (10 * 1000)

実行例:

$ ghc -W -ffi -o fib2.exe fib2.hs
$ ./fib2.exe 24 25
(226,1)
(226,1)
(233,2)
(240,3)
(254,5)
(277,8)
(320,13)
(403,21)
...

参照: 音階についてのおしゃべり