Guest User

Untitled

a guest
Jul 21st, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.82 KB | None | 0 0
  1. module Main (main) where
  2.  
  3. import qualified Data.ByteString as B
  4. import qualified Data.ByteString.Char8 as C
  5.  
  6. import Data.Word
  7. import Data.Int
  8. import Data.Bits
  9.  
  10. class Packable a where
  11. toByteString :: a -> B.ByteString
  12.  
  13. instance Packable Word32 where
  14. toByteString i =
  15. fromIntegral (i .&. 0x000000ff) `B.cons`
  16. (fromIntegral ((i .&. 0x0000ff00) `shiftR` 8) `B.cons`
  17. (fromIntegral ((i .&. 0x00ff0000) `shiftR` 16) `B.cons`
  18. (fromIntegral ((i .&. 0xff000000) `shiftR` 24) `B.cons`
  19. B.empty)))
  20.  
  21. instance Packable Word16 where
  22. toByteString i =
  23. fromIntegral (i .&. 0x00ff) `B.cons`
  24. (fromIntegral ((i .&. 0xff00) `shiftR` 8) `B.cons`
  25. B.empty)
  26.  
  27. instance Packable Int16 where
  28. toByteString i =
  29. fromIntegral (i .&. 0x00ff) `B.cons`
  30. (fromIntegral ((i .&. 0xff00) `shiftR` 8) `B.cons`
  31. B.empty)
  32.  
  33. data RIFFchunk = RIFF Word32
  34.  
  35. instance Packable RIFFchunk where
  36. toByteString (RIFF chunkSize) =
  37. C.pack "RIFF" `B.append`
  38. toByteString chunkSize `B.append`
  39. C.pack "WAVE"
  40.  
  41. data FormatChunk = FMT Word32 Word16 Word16 Word32 Word32 Word16 Word16 Word16
  42.  
  43. instance Packable FormatChunk where
  44. toByteString (FMT chunkSize
  45. audioFormat
  46. numChannels
  47. sampleRate
  48. byteRate
  49. blockAlign
  50. bitsPerSample
  51. extraParamSize) =
  52. C.pack "fmt " `B.append`
  53. toByteString chunkSize `B.append`
  54. toByteString audioFormat `B.append`
  55. toByteString numChannels `B.append`
  56. toByteString sampleRate `B.append`
  57. toByteString byteRate `B.append`
  58. toByteString blockAlign `B.append`
  59. toByteString bitsPerSample `B.append`
  60. toByteString extraParamSize
  61.  
  62. data DataChunkHeader = DATA Word32
  63. instance Packable DataChunkHeader where
  64. toByteString (DATA chunkSize) =
  65. C.pack "data" `B.append`
  66. toByteString chunkSize
  67.  
  68. clicks :: Double -> [Double]
  69. clicks freq = [0, 1/freq..]
  70.  
  71. sample :: Double -> Double -> Double
  72. sample f t = sin (2 * pi * f * t)
  73.  
  74. quantize :: Double -> Int16
  75. quantize v = truncate $ fromIntegral (maxBound::Int16) * v
  76.  
  77. main :: IO ()
  78. main = do
  79. let formatChunk = FMT 18 1 1 44100 88200 2 16 0
  80. packedFmt = toByteString formatChunk
  81. num_samples = 44100
  82. riffChunk = RIFF (fromIntegral (4 +
  83. B.length packedFmt +
  84. 4 + 4 + num_samples * 2))
  85. dataChunkHeader = DATA (fromIntegral num_samples * 2)
  86. rate = 44100
  87. freq = 440
  88. wave = map (sample freq) (clicks rate)
  89. B.putStr $ toByteString riffChunk
  90. B.putStr packedFmt
  91. B.putStr $ toByteString dataChunkHeader
  92. mapM_ B.putStr $ take (fromIntegral num_samples) $
  93. map (toByteString . quantize) wave
Add Comment
Please, Sign In to add comment