tidal-playground/raw-sound.hs

91 lines
2 KiB
Haskell
Raw Permalink Normal View History

2020-05-31 12:10:52 +00:00
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{- Inspiration: https://www.youtube.com/watch?v=FYTZkE5BZ-0&app=desktop
-}
import Protolude hiding (note)
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.Builder as B
import System.Process
import Text.Printf (printf)
import Data.List (zipWith3)
outputFilePath :: FilePath
outputFilePath = "output.bin"
sampleRate :: Float
sampleRate = 48000
volume :: Float
volume = 0.5
type Duration = Float
type Hz = Float
type Seconds = Float
type Pulse = Float
type Soundwave = [Pulse]
type Beats = Float
bpm :: Beats
bpm = 120
beatDuration :: Seconds
beatDuration = 60.0/bpm
standardFreq :: Hz
standardFreq = 440
f n = standardFreq * ((2 ** (1/12)) ** n)
major = [0,2,4,5,7,9,11,12]
freq :: Hz -> Seconds -> [Float]
freq hz duration = map (* volume) $ zipWith3 (\x y z -> x * y * z) attack release output
where
nbpulse = sampleRate * duration
attackduration = 0.05
attack = map (min 1) [0, (1 / (attackduration * nbpulse)).. ]
release = reverse (take (length output) attack)
output = map (sin . (* step)) [0.0 .. sampleRate * duration]
step = (hz * 2 * pi) / sampleRate
note n l = freq (f n) (beatDuration * l)
maintrack =
[ note 0 0.25
, note 0 0.25
, note 0 0.25
, note 0 0.25
, note 0 0.5
, note 0 0.25
, note 0 0.25
, note 0 0.25
, note 0 0.25
, note 0 0.5
, note 5 0.25
, note 5 0.25
, note 5 0.25
, note 5 0.25
, note 5 0.5
, note 3 0.25
, note 3 0.25
, note 3 0.25
, note 3 0.25
, note 3 0.5
, note (-2) 0.5
]
wave :: Soundwave
wave = concat (maintrack <> maintrack)
save :: FilePath -> IO ()
save fp =
B.writeFile fp $ B.toLazyByteString $ fold $ map B.floatLE wave
play :: IO ()
play = do
save outputFilePath
void $ runCommand $ printf "ffplay -showmode 1 -f f32le -ar %f %s" sampleRate outputFilePath