Me playing with tidalcycles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

raw-sound.hs 2.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. {-# LANGUAGE NoImplicitPrelude #-}
  2. {-# LANGUAGE OverloadedStrings #-}
  3. {- Inspiration: https://www.youtube.com/watch?v=FYTZkE5BZ-0&app=desktop
  4. -}
  5. import Protolude hiding (note)
  6. import qualified Data.ByteString.Lazy as B
  7. import qualified Data.ByteString.Builder as B
  8. import System.Process
  9. import Text.Printf (printf)
  10. import Data.List (zipWith3)
  11. outputFilePath :: FilePath
  12. outputFilePath = "output.bin"
  13. sampleRate :: Float
  14. sampleRate = 48000
  15. volume :: Float
  16. volume = 0.5
  17. type Duration = Float
  18. type Hz = Float
  19. type Seconds = Float
  20. type Pulse = Float
  21. type Soundwave = [Pulse]
  22. type Beats = Float
  23. bpm :: Beats
  24. bpm = 120
  25. beatDuration :: Seconds
  26. beatDuration = 60.0/bpm
  27. standardFreq :: Hz
  28. standardFreq = 440
  29. f n = standardFreq * ((2 ** (1/12)) ** n)
  30. major = [0,2,4,5,7,9,11,12]
  31. freq :: Hz -> Seconds -> [Float]
  32. freq hz duration = map (* volume) $ zipWith3 (\x y z -> x * y * z) attack release output
  33. where
  34. nbpulse = sampleRate * duration
  35. attackduration = 0.05
  36. attack = map (min 1) [0, (1 / (attackduration * nbpulse)).. ]
  37. release = reverse (take (length output) attack)
  38. output = map (sin . (* step)) [0.0 .. sampleRate * duration]
  39. step = (hz * 2 * pi) / sampleRate
  40. note n l = freq (f n) (beatDuration * l)
  41. maintrack =
  42. [ note 0 0.25
  43. , note 0 0.25
  44. , note 0 0.25
  45. , note 0 0.25
  46. , note 0 0.5
  47. , note 0 0.25
  48. , note 0 0.25
  49. , note 0 0.25
  50. , note 0 0.25
  51. , note 0 0.5
  52. , note 5 0.25
  53. , note 5 0.25
  54. , note 5 0.25
  55. , note 5 0.25
  56. , note 5 0.5
  57. , note 3 0.25
  58. , note 3 0.25
  59. , note 3 0.25
  60. , note 3 0.25
  61. , note 3 0.5
  62. , note (-2) 0.5
  63. ]
  64. wave :: Soundwave
  65. wave = concat (maintrack <> maintrack)
  66. save :: FilePath -> IO ()
  67. save fp =
  68. B.writeFile fp $ B.toLazyByteString $ fold $ map B.floatLE wave
  69. play :: IO ()
  70. play = do
  71. save outputFilePath
  72. void $ runCommand $ printf "ffplay -showmode 1 -f f32le -ar %f %s" sampleRate outputFilePath