wavesurfer (empty) → 0.0.1
raw patch · 4 files changed
+191/−0 lines, 4 filesdep +basedep +binarydep +bytestringsetup-changed
Dependencies added: base, binary, bytestring, bytestring-lexing, bytestring-show, delimited-text
Files
- LICENSE +24/−0
- Setup.hs +2/−0
- Sound/WaveSurfer.hs +138/−0
- wavesurfer.cabal +27/−0
+ LICENSE view
@@ -0,0 +1,24 @@+Copyright (c) Stefan Kersten 2008++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Sound/WaveSurfer.hs view
@@ -0,0 +1,138 @@+-- | Parse WaveSurfer files.+--+-- WaveSurfer is an application for analysing and annotating audio files.+-- <http://www.speech.kth.se/wavesurfer/>+--+-- A WaveSurfer file consists of lines containing a label and corresponding+-- onsets and offsets in seconds:+--+-- > onset offset label+--+-- This library supports an extended file format, where the first label can be+-- followed by additional key-value pairs, separated by colons:+--+-- > onset offset label key1[:value1] key2[:value2] ...+--+module Sound.WaveSurfer (+ Time, DTime,+ Label, Attribute,+ Record(..), duration,+ Result,+ encode, decode,+ interact+) where++import Data.Binary.Put (Put, runPut, putByteString)+import Data.Maybe (mapMaybe)++import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Lazy.Char8 as BLC+import Data.ByteString.Lex.Double (readDouble)++import Text.Delimited (Result)+import qualified Text.Delimited as DT+import Prelude hiding (interact)+import Text.Show.ByteString (putAscii, showp, unlinesP, unwordsP)+import qualified Text.Show.ByteString as ShowP++-- | Time type.+type Time = Double++-- | Type for time differences.+type DTime = Time++-- | Record label.+type Label = BS.ByteString++-- | Key-value pair.+type Attribute = (Label, Maybe Label)++-- | Record representing a single line in the WaveSurfer file.+data Record = Record {+ onset :: Time,+ offset :: Time,+ label :: Label,+ attributes :: [Attribute]+} deriving (Eq, Show)++-- | A file's content is a list of records.+type Content = [Record]++-- | Return the duration of a 'Record' in seconds.+duration :: Record -> DTime+duration e = offset e - onset e++whiteSpace :: [Char]+whiteSpace = [' ', '\t']++-- | Comment character.+comment :: Char+comment = '#'++putAttribute :: Attribute -> Put+putAttribute (key, value) = do+ putByteString key+ case value of+ Just v -> putAscii ':' >> putByteString v+ Nothing -> return ()++putRecord :: Record -> Put+putRecord r = unwordsP ([t0, t1, putByteString (label r)] ++ attrs)+ where+ t0 = showp (onset r)+ t1 = showp (offset r)+ attrs = map putAttribute (attributes r)++putContent :: Content -> Put+putContent = unlinesP . map putRecord++-- | Encode 'Content' to a lazy 'ByteString'.+encode :: Content -> ByteString+encode = runPut . putContent++-- | Monad instance for Either.+instance Monad (Either a) where+ return = Right+ x >>= f = case x of+ Left a -> Left a+ Right r -> f r++-- | Decode attributes.+decodeAttributes :: DT.Record -> Result [Attribute]+decodeAttributes = return . map f+ where f s = let (k, v) = BSC.break (==':') s+ v' = BS.tail v+ in (k, if BS.null v' then Nothing else Just v')++-- | Decode a 'Double'.+decodeDouble :: DT.Field -> Result Double+decodeDouble s = case readDouble s of+ Just (d, _) -> Right d+ Nothing -> Left ("Couldn't parse Double: " ++ show s)++-- | Decode a 'Record'.+decodeRecord :: DT.Record -> Result Record+decodeRecord (t0:t1:lbl:attrs) = do+ t0' <- decodeDouble t0+ t1' <- decodeDouble t1+ attrs' <- decodeAttributes attrs+ return (Record t0' t1' lbl attrs')+decodeRecord r = Left ("Couldn't parse record: " ++ show r)++-- | Decode 'Content' from a lazy 'ByteString'.+decode :: ByteString -> Result Content+decode s = do+ xs <- DT.decode whiteSpace s+ mapM decodeRecord (filter f xs)+ where+ f [] = False+ f (r:rs) = not (BSC.null r) && (BSC.head r /= comment)++interact :: (Record -> Record) -> ByteString -> Result ByteString+interact f s = do+ c <- decode s+ let c' = map f c+ return (encode c')
+ wavesurfer.cabal view
@@ -0,0 +1,27 @@+name: wavesurfer+version: 0.0.1+synopsis: Parse WaveSurfer files+description: Parse WaveSurfer files+license: BSD3+license-file: LICENSE+category: Data, Sound, Text+copyright: Copyright (c) Stefan Kersten 2008+author: Stefan Kersten+maintainer: Stefan Kersten+stability: provisional+homepage: http://code.haskell.org/~StefanKersten/code/wavesurfer+tested-with: GHC == 6.10.1+build-type: Simple+cabal-version: >= 1.2++library+ exposed-modules: Sound.WaveSurfer++ build-depends: base >= 3,+ binary >= 0.4,+ bytestring,+ bytestring-lexing,+ bytestring-show,+ delimited-text++ ghc-options: -O2 -funbox-strict-fields