hsc3-sf (empty) → 0.7
raw patch · 8 files changed
+229/−0 lines, 8 filesdep +basedep +bytestringdep +hoscsetup-changed
Dependencies added: base, bytestring, hosc
Files
- Help/rescale.help.hs +19/−0
- README +12/−0
- Setup.lhs +3/−0
- Sound/File/Decode.hs +43/−0
- Sound/File/Encode.hs +16/−0
- Sound/File/Encoding.hs +17/−0
- Sound/File/NeXT.hs +90/−0
- hsc3-sf.cabal +29/−0
+ Help/rescale.help.hs view
@@ -0,0 +1,19 @@+-- Change the gain of an audio file.++import qualified Sound.File.NeXT as N+import System.Environment++rescale :: Double -> FilePath -> IO ()+rescale n fn = do + (N.Header nf _ sr nc, d) <- N.read fn+ let d' = map (map (* n)) d+ N.write (fn ++ ".rescale.au") (N.Header nf N.Float sr nc) d'++main :: IO ()+main = do + [g, f] <- getArgs+ rescale (read g) f++{-+rescale 0.25 "/home/rohan/audio/text.snd"+-}
+ README view
@@ -0,0 +1,12 @@+hsc3-sf - simple sound file input/output++hsc3-sf provides Sound.File.NeXT, a Haskell module that +provides simple minded sound file input/output for +NeXT/Sun format sound files. For more comprehensive+sound file support in haskell see hsndfile.++ http://slavepianos.org/rd+ http://darcs.k-hornz.de/repos/hsndfile/++(c) rohan drape, 2006-2009+ gpl, http://gnu.org/copyleft/
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ Sound/File/Decode.hs view
@@ -0,0 +1,43 @@+module Sound.File.Decode ( decode ) where++import Data.Int+import qualified Data.ByteString.Lazy as B+import Sound.OpenSoundControl.Byte+import Sound.File.Encoding++setsOf :: Int -> [a] -> [[a]]+setsOf _ [] = []+setsOf n l = x : setsOf n y + where (x, y) = splitAt n l++channel :: [[a]] -> Int -> [a]+channel l n = map (!!n) l++deinterleave :: Int -> [a] -> [[a]]+deinterleave n l = map (channel (setsOf n l)) [0..n-1]++bSetsOf :: Int64 -> B.ByteString -> [B.ByteString]+bSetsOf _ b | B.null b = []+bSetsOf n b | otherwise = x : bSetsOf n y + where (x, y) = B.splitAt n b++decodef32 :: Int -> B.ByteString -> [[Double]]+decodef32 n = deinterleave n . map decode_f32 . bSetsOf 4++decodei16 :: Int -> B.ByteString -> [[Int]]+decodei16 n = deinterleave n . map decode_i16 . bSetsOf 2++decodei8 :: Int -> B.ByteString -> [[Int]]+decodei8 n = deinterleave n . map decode_i8 . bSetsOf 1++i8_f :: [Int] -> [Double]+i8_f = map ((/ 128.0) . fromIntegral)++i16_f :: [Int] -> [Double]+i16_f = map ((/ 32768.0) . fromIntegral)++decode :: Encoding -> Int -> B.ByteString -> [[Double]]+decode enc nc b | enc == Linear8 = map i8_f (decodei8 nc b)+ | enc == Linear16 = map i16_f (decodei16 nc b)+ | enc == Float = decodef32 nc b+ | otherwise = undefined
+ Sound/File/Encode.hs view
@@ -0,0 +1,16 @@+module Sound.File.Encode ( encode ) where++import qualified Data.ByteString.Lazy as B+import Data.List+import Sound.OpenSoundControl.Byte+import Sound.File.Encoding++interleave :: [[a]] -> [a]+interleave = concat . transpose++encodef32 :: [[Double]] -> B.ByteString+encodef32 = B.concat . map encode_f32 . interleave++encode :: Encoding -> [[Double]] -> B.ByteString+encode enc d | enc == Float = encodef32 d+ | otherwise = undefined
+ Sound/File/Encoding.hs view
@@ -0,0 +1,17 @@+module Sound.File.Encoding where++data Encoding = Linear8+ | Linear16+ | Linear32+ | Float+ | Double+ deriving (Eq, Show)++-- | Bytes per sample at specified encoding.+sizeOf :: Encoding -> Int+sizeOf Linear8 = 1+sizeOf Linear16 = 2+sizeOf Linear32 = 4+sizeOf Float = 4+sizeOf Double = 8+
+ Sound/File/NeXT.hs view
@@ -0,0 +1,90 @@+-- | Read and write NeXT/Sun format sound files.+module Sound.File.NeXT ( Header(..)+ , header+ , read+ , write+ , module Sound.File.Encoding ) where++import Prelude hiding (read)+import qualified Data.ByteString.Lazy as B+import Data.Int+import Data.Maybe+import Sound.OpenSoundControl.Byte+import Sound.File.Decode+import Sound.File.Encode+import Sound.File.Encoding++type Offset = Int64+type SampleRate = Int+type FrameCount = Int+type ChannelCount = Int++-- | Data type encapsulating sound file meta data.+data Header = Header { frameCount :: FrameCount+ , encoding :: Encoding+ , sampleRate :: SampleRate+ , channelCount :: ChannelCount }+ deriving (Eq, Show)++toEncoding :: Int -> Encoding+toEncoding 2 = Linear8+toEncoding 3 = Linear16+toEncoding 5 = Linear32+toEncoding 6 = Float+toEncoding 7 = Double+toEncoding _ = undefined++fromEncoding :: Encoding -> Int+fromEncoding Linear8 = 2+fromEncoding Linear16 = 3+fromEncoding Linear32 = 5+fromEncoding Float = 6+fromEncoding Double = 7++-- | The NeXT header magic number.+magic :: Int+magic = 0x2e736e64++-- | Byte-encode a NeXT header.+encodeHeader :: Header -> B.ByteString+encodeHeader (Header nf enc sr nc) = B.concat (map encode_i32 h)+ where nb = nf * nc * sizeOf enc+ h = [magic, 28, nb, (fromEncoding enc), sr, nc, 0]++-- | Byte-decode a NeXT header.+decodeHeader :: B.ByteString -> Maybe (Offset, Header)+decodeHeader u = if m == magic then Just (off, Header nf enc sr nc) else Nothing+ where f n = decode_i32 (B.drop n u)+ m = f 0+ off = fromIntegral (f 4)+ nb = f 8+ enc = toEncoding (f 12)+ sr = f 16+ nc = f 20+ nf = nb `div` (nc * sizeOf enc)++writeB :: FilePath -> Header -> B.ByteString -> IO ()+writeB fn (Header nf enc sr nc) d = B.writeFile fn b+ where h = encodeHeader (Header nf enc sr nc)+ b = B.append h d++-- | Write sound file, data is non-interleaved.+write :: FilePath -> Header -> [[Double]] -> IO ()+write fn (Header nf enc sr nc) d = writeB fn (Header nf enc sr nc) b+ where b = encode enc d++readB :: FilePath -> IO (Header, B.ByteString)+readB fn = do b <- B.readFile fn+ let (off, h) = fromMaybe undefined (decodeHeader b)+ return (h, B.drop off b)++-- | Read sound file meta data.+header :: FilePath -> IO Header+header fn = do (h, _) <- read fn+ return h++-- | Read sound file, data is interleaved.+read :: FilePath -> IO (Header, [[Double]])+read fn = do (Header nf enc sr nc, b) <- readB fn+ let d = decode enc nc b+ return (Header nf enc sr nc, d)
+ hsc3-sf.cabal view
@@ -0,0 +1,29 @@+Name: hsc3-sf+Version: 0.7+Synopsis: Haskell SuperCollider SoundFile+Description: Trivial NeXT/Sun sound file input/output.+ For almost all use cases please see Stefan + Kersten's hsndfile package.+License: GPL+Category: Sound+Copyright: (c) Rohan Drape, 2006-2009+Author: Rohan Drape+Maintainer: rd@slavepianos.org+Stability: Experimental+Homepage: http://slavepianos.org/rd/f/924736/+Tested-With: GHC == 6.8.2+Build-Type: Simple+Cabal-Version: >= 1.6++Data-files: README+ Help/rescale.help.hs++Library+ Build-Depends: base == 3.*,+ bytestring,+ hosc == 0.7+ GHC-Options: -Wall -fwarn-tabs+ Exposed-modules: Sound.File.NeXT+ Other-modules: Sound.File.Encoding+ Sound.File.Encode+ Sound.File.Decode