audacity 0.0.1.2 → 0.0.1.3
raw patch · 3 files changed
+107/−4 lines, 3 filesdep ~basedep ~directorydep ~non-emptynew-component:exe:sox-splitPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base, directory, non-empty, storablevector, utility-ht
API changes (from Hackage documentation)
Files
- audacity.cabal +28/−2
- example/Common.hs +2/−2
- example/Split.hs +77/−0
audacity.cabal view
@@ -1,5 +1,5 @@ Name: audacity-Version: 0.0.1.2+Version: 0.0.1.3 Synopsis: Interchange with the Audacity sound signal editor Description: This package provides functions@@ -10,6 +10,12 @@ . We provide some examples that are useful on its own: .+ * @sox-split@:+ Split an audio file according to a label track.+ Audacity provides this function by itself.+ You can use placeholders like @%s@ and @%02d@+ in order to compose the names of the parts from the labels and positions.+ . * @sox-concat@: Concatenate a sequence of sound files with matching sampling rates and numbers of channels using SoX@@ -35,7 +41,7 @@ Cabal-Version: >=1.10 Source-Repository this- Tag: 0.0.1.2+ Tag: 0.0.1.3 Type: darcs Location: http://hub.darcs.net/thielema/audacity @@ -75,6 +81,26 @@ Hs-Source-Dirs: src Default-Language: Haskell2010 GHC-Options: -Wall++Executable sox-split+ Main-Is: Split.hs+ Other-Modules: Common+ Hs-Source-Dirs: example+ Default-Language: Haskell2010+ GHC-Options: -Wall+ If flag(buildExamples)+ Build-Depends:+ audacity,+ soxlib >=0.0 && <0.1,+ storablevector,+ directory,+ optparse-applicative >=0.11 && <0.15,+ filepath >=1.3 && <1.5,+ non-empty,+ utility-ht,+ base+ Else+ Buildable: False Executable sox-concat Main-Is: Concatenate.hs
example/Common.hs view
@@ -80,7 +80,7 @@ some :: OP.Parser a -> OP.Parser (NonEmpty.T [] a) some p = OPInt.fromM $ OP.liftA2 (!:) (OPInt.oneM p) (OPInt.manyM p) -parseArgs :: OP.Parser (NonEmpty.T [] String, String)+parseArgs :: OP.Parser (NonEmpty.T [] FilePath, FilePath) parseArgs = OP.liftA2 (,) (some (OP.strArgument (OP.metavar "SRC")))@@ -92,5 +92,5 @@ (OP.helper <*> parser) (OP.fullDesc <> OP.progDesc desc) -multiArgs :: String -> IO (NonEmpty.T [] String, String)+multiArgs :: String -> IO (NonEmpty.T [] FilePath, FilePath) multiArgs desc = OP.execParser $ info desc parseArgs
+ example/Split.hs view
@@ -0,0 +1,77 @@+module Main where++import Common (defaultSampleRate, info, withSound, writerInfoFromFormat)++import qualified Sound.Audacity.LabelTrack as LabelTrack+import qualified Sound.SoxLib as SoxLib++import qualified Data.StorableVector.Lazy as SVL++import qualified Options.Applicative as OP+import Control.Monad (forM_)++import qualified Data.List as List+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Tuple.HT (uncurry3)+import Data.Ord.HT (comparing)+import Data.Char (isDigit)+import Data.Int (Int32)++import Text.Printf (printf)+++formatName :: String -> Int -> String -> String+formatName fmt k label =+ let go ('%':cs0) =+ case cs0 of+ 's':cs1 -> label ++ go cs1+ '%':cs1 -> '%' : go cs1+ _ ->+ case span isDigit cs0 of+ (digits,'d':cs2) -> printf ("%"++digits++"d") k ++ go cs2+ _ -> '%' : go cs0+ go (c:cs) = c : go cs+ go [] = []+ in go fmt++split ::+ LabelTrack.T Int a -> Int -> SVL.Vector Int32 ->+ [(a, SVL.Vector Int32)]+split labels numChan sig =+ snd $+ List.mapAccumL+ (\(tOld,sigOld) ((t0,t1),label) ->+ let sigNew = SVL.drop (numChan*(t0-tOld)) sigOld+ in ((t0,sigNew), (label, SVL.take (numChan*(t1-t0)) sigNew)))+ (0, sig) $+ List.sortBy (comparing fst) $ LabelTrack.decons labels++run :: FilePath -> FilePath -> FilePath -> IO ()+run labelFile input output = do+ labels <- LabelTrack.readFile labelFile+ withSound input $ \fmtIn mrate numChan sig -> do+ let rate = fromMaybe defaultSampleRate mrate+ pieces =+ split (LabelTrack.mapTime (\t -> round (t*rate)) labels) numChan sig+ forM_ (zip [0..] pieces) $ \(k,(label,piece)) ->+ SoxLib.withWrite+ (writerInfoFromFormat fmtIn)+ (formatName output k label)+ (flip SoxLib.writeStorableVectorLazy piece)++parseArgs :: OP.Parser (FilePath, FilePath, FilePath)+parseArgs =+ OP.liftA3 (,,)+ (OP.strArgument (OP.metavar "LABELTRACK"))+ (OP.strArgument (OP.metavar "INPUT"))+ (OP.strOption+ (OP.long "output" <> OP.metavar "FMT" <> OP.value "%s.wav"+ <> OP.help "include %s for labels and %03d for counts"))++main :: IO ()+main =+ SoxLib.formatWith $+ uncurry3 run =<<+ OP.execParser+ (info "Split audio file according to label track" parseArgs)