packages feed

repa-sndfile-3.2.3.2: exec/gensine.hs

{-# LANGUAGE TypeOperators #-}
{-|
Module      : $Header$
CopyRight   : (c) 8c6794b6
License     : BSD3
Maintainer  : 8c6794b6@gmail.com
Stability   : experimental
Portability : non-portable

Generates sine wave.

-}
module Main where

import Control.Monad (void)
import Data.Array.Repa (Array, DIM2, computeP)
import Data.Array.Repa.Repr.ForeignPtr (F)
import qualified Sound.File.Sndfile as S
import Sound.File.Sndfile.Buffer.Vector
import System.Environment (getArgs)

import Data.Array.Repa.IO.Sndfile
import Data.Array.Repa.IO.Sndfile.Examples (genSine, genSineV)


main :: IO ()
main = do
  args <- getArgs
  case args of
    dur:frq:path:mode:_ ->
      let dur' = read dur
          frq' = read frq
          fmt  = wav16 {frames = 48000 * dur'}
      in  case mode of
        "buf" -> do
          arr <- computeP (genSine dur' frq') :: IO (Array F DIM2 Double)
          writeSF path fmt arr
        "vec" -> void $ S.writeFile fmt path (toBuffer $ genSineV dur' frq')
        _     -> usage
    _ -> usage

usage :: IO ()
usage = error "Usage: duration freq path [buf|vec]"

{- ---------------------------------------------------------------------------
 - Write stereo sound, using different frequency for each channel.
 - Modify header format to 'channels = 2' and run.

genSine :: Int -> Double -> Array DIM2 Double
genSine dur frq =
  let sh = Z :. 2 :. (dur * 48000) :: DIM2
  in  fromFunction sh $ \(_ :. i :. j) ->
        sin (frq * (fromIntegral i + 1) * fromIntegral j * pi * 2 / 48000)

Generating 30 seconds of 440 hz sine wav took about 0.2 sec with repa, in 8 core
machine, using 8 threads. It uses 4x more memory of the size of result file.

For just reading and writing sound files as haskell data, storable vector took
almost same execution time. It took about 0.25sec in same machine, memory usage
was less.

-}