playground/haskell/Music.hs

66 lines
1.7 KiB
Haskell

-- https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString-Lazy.html#t:LazyByteString
import qualified Data.ByteString.Lazy as BL
-- https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString-Builder.html
import qualified Data.ByteString.Builder as B
import qualified Data.Foldable
import qualified System.Process
import qualified Text.Printf
type Hz = Float
type Seconds = Float
type Signal = [Float]
-- Byte strings with Little Endian 32 bit float
-- B.floatLE n :: B.Builder
outFile :: FilePath
outFile = "out.bin"
-- volume :: Float
-- volume = 0.2
-- Number of samples per second
-- ie, number of float values per second
sampleRate :: Hz
sampleRate = 48000
-- step :: Float
-- step = 0.01
duration :: Float
duration = 2.0
wave :: Float -> Hz -> Seconds -> Signal
wave volume freq duration
= map (* volume) -- adjust volume
$ map sin -- generate wave
$ map (* step) [0.0 .. sampleRate * duration]
where
step = (freq * 2 * pi) / sampleRate
sound :: Signal
sound = concat $ map (++)
[wave 0.2 440 duration
wave 0.2 frq secs
toBS :: [Float] -> B.Builder
toBS wav = Data.Foldable.fold $ map B.floatLE wav
-- LazyByteString: Serializable-friendly form of ByteString
-- https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString-Lazy.html#t:LazyByteString
save :: FilePath -> IO ()
save outfile = BL.writeFile outfile $ B.toLazyByteString $ toBS sound
play :: IO ()
play = do
save outFile
_ <- System.Process.runCommand
$ Text.Printf.printf "ffplay -showmode 1 -f f32le -ar %f %s" sampleRate outFile
return ()