packages feed

truelevel (empty) → 0.1

raw patch · 5 files changed

+240/−0 lines, 5 filesdep +WAVEdep +basedep +parseargssetup-changed

Dependencies added: WAVE, base, parseargs

Files

+ COPYING view
@@ -0,0 +1,34 @@+Copyright (C) 2007 Bart Massey+ALL RIGHTS RESERVED++[This program is licensed under the "3-clause ('new') BSD License"]++Redistribution and use in source and binary forms, with or+without modification, are permitted provided that the+following conditions are met:+    * Redistributions of source code must retain the above+      copyright notice, this list of conditions and the following+      disclaimer.+    * 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.+    * Neither the name of Bart Massey, nor the names+      of other affiliated organizations, nor the names+      of other contributors may be used to endorse or promote+      products derived from this software without specific prior+      written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ README view
@@ -0,0 +1,20 @@+truelevel -- audio file compresor / limiter+version 0.1+Bart Massey <bart@cs.pdx.edu>+8 March 2008++This program is a simple command-line compressor / limiter+for WAVE format audio files.  There is precious little+documentation at this point; that needs to be fixed soon.++I have used this code with ghc 6.6 and ghc 6.8 on Linux,+although the current cabal setup has only been tested with+cabal 1.2 and ghc 6.8.  Other than the lack of+documentation, it is a fairly standard Hackage-ready+package, to the extent I know how to construct such.++I'm not really working on this Haskell code any longer; I+rewrote it in Java for a project I'm working on.  However, I+think it's a nice demo app for my WAVE library.++Have fun with it, and let me know if there are problems.
+ Setup.hs view
@@ -0,0 +1,7 @@+--- Copyright (C) 2007 Bart Massey+--- ALL RIGHTS RESERVED+--- Please see the file COPYING in this software+--- distribution for license information.++import Distribution.Simple+main = defaultMain
+ truelevel.cabal view
@@ -0,0 +1,19 @@+Name: truelevel+Build-Type: Simple+Description: An audio file compressor / limiter.  This+             program will adjust the dynamic range of a WAVE file.+Version: 0.1+License: BSD3+License-File: COPYING+Copyright: Copyright (C) 2006-2008 Bart Massey+Author: Bart Massey <bart@cs.pdx.edu>+Maintainer: Bart Massey <bart@cs.pdx.edu>+Homepage: http://wiki.cs.pdx.edu/bartforge/truelevel+Stability: Alpha+Synopsis: Audio file compressor-limiter+Category: Audio+Build-Depends: base, WAVE, parseargs+Extra-Source-Files: README++Executable: truelevel+Main-Is: truelevel.hs
+ truelevel.hs view
@@ -0,0 +1,160 @@+--- Copyright (C) 2007 Bart Massey+--- ALL RIGHTS RESERVED+--- Please see the end of this file for license information.++module Main+where++import Data.List+import Data.Maybe+import System.Environment+import System.Console.ParseArgs+import Data.WAVE+import TrueLevelArgs++-- Create overlapping tiles of n samples.  Each tile is a+-- list of n samples together with a list of n + 2m samples+-- (in general) representing the surrounding window.+offset_tile :: Int -> Int -> [a] -> [([a], [a])]+offset_tile n m s =+    one_tile (0, n, m) s+    where+      one_tile (l, c, r) s =+          let target = take c (drop l s)+              (window, l', s') =+                  if l < r+                  then (take (l + c + r) s,  (l + c) `min` (r + c), s)+                  else (take (r + c + r) (drop (l - r) s), l, drop c s)+          in+            if null target+            then []+            else (target, window) : one_tile (l', c, r) s'++avg :: (Fractional a) => [a] -> a+avg l = sum l / fromIntegral (length l)++--- Estimate peak amplitude using rms power+rms :: [Double] -> Double+rms s = 2 * sqrt (2 * sum (map (\x -> x * x) s) / fromIntegral (length s))++--- Estimate peak amplitude as twice highest absolute peak+--- of low-pass+--- XXX fixme: low-pass is moving average for now+peak :: [Double] -> Double+peak s = 2 * (maximum . map abs . map avg . tile 3 2) s++make_window :: Int -> Int -> [Double]+make_window n w =+    let tri = [ fromIntegral i / fromIntegral (w + 1) |+                i <- [ 1 .. w ] ]+        flat = replicate (n - 2 * w) 1+    in tri ++ flat ++ reverse tri++vprod :: [Double] -> [Double] -> [Double]+vprod l1 l2 = map (\(v1, v2) -> v1 * v2) (zip l1 l2)++compress :: Double -> Double -> Double -> Double+          -> (Double, [[Double]]) -> [[Double]]+compress l h l' h' (s, a)  =+    if s <= 0.0001 then+        map (map (\v -> 0)) a+    else if s >= h then+        scale (h' / s)+    else if s <= l then+        scale (l' / s)+    else let s' = l' + (h' - l') * (s - l) / (h - l) in+        scale (s' / s)+    where+      scale v = map (map (v *)) a++ac :: [Double] -> [Double]+ac tick = map (\v -> v - avg tick) tick++score_tick :: ([Double] -> [Double])+           -> ([Double] -> Double)+           -> [Double]+           -> ([[Double]], [[Double]])+           -> (Double, [[Double]])+score_tick bias power window (target, surround) = +    let powerf = map (power . bias . (vprod window))+        score = maximum (powerf (transpose surround)) in+    (score, target)++main :: IO ()+main = do+    args <- parseArgsIO ArgsComplete argd+    --- get the input+    h <- getArgStdio args OptionInputFile ReadMode+    wav <- hGetWAVE h+    let samples =  map (map sampleToDouble)+                       (waveSamples wav)+    --- group into ticks+    let hd = waveHeader wav+    let rate = waveFrameRate hd+    let tick_ms = fromJust (getArgInt args OptionTickMS)+    let tick_samples = rate * tick_ms `div` 1000+    let window_pct =+            fromJust (getArgDouble args OptionWindowPercent) / 100+    let window_edge = floor ((window_pct / 2) * fromIntegral tick_samples)+    let overlap = case getArgDouble args OptionWindowOverlap of+                    Nothing -> 2 * window_edge+                    Just p -> floor (p * fromIntegral tick_samples / 100)+    let offset_ticks = offset_tile tick_samples overlap samples+    --- score ticks+    let window = make_window tick_samples overlap+    let bias = if gotArg args OptionDCBias+               then id+               else ac+    let power = if gotArg args OptionUseRMS+                then rms+                else peak+    let scored_ticks = map (score_tick bias power window) offset_ticks+    --- scale the input+    let low_limit =+            fromJust (getArgDouble args OptionLowLimit)  / 100+    let high_limit =+            fromJust (getArgDouble args OptionHighLimit)  / 100+    let low_output =+            fromJust (getArgDouble args OptionLowOutput) / 100+    let high_output =+            fromJust (getArgDouble args OptionHighOutput) / 100+    let lev = compress low_limit high_limit low_output high_output+    let scaled = concatMap lev scored_ticks+    --- write the output+    let samples' = map (map doubleToSample) scaled+    let wav' = WAVE { waveHeader = hd,+                      waveSamples = samples' }+    h' <- getArgStdio args OptionOutputFile WriteMode+    hPutWAVE h' wav'+++    +--- Redistribution and use in source and binary forms, with or+--- without modification, are permitted provided that the+--- following conditions are met:+---     * Redistributions of source code must retain the above+---       copyright notice, this list of conditions and the following+---       disclaimer.+---     * 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.+---     * Neither the name of Bart Massey, nor the names+---       of other affiliated organizations, nor the names+---       of other contributors may be used to endorse or promote+---       products derived from this software without specific prior+---       written permission.+--- +--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.