I created the following source code by referring to get_normalized_volume from alsa-utils/alsa-mixer/volume_mapping.c
{-# LANGUAGE ScopedTypeVariables #-}
import qualified Sound.ALSA.Mixer as AM
maxLinearDbScale :: AM.CLong
maxLinearDbScale = 24
gainMute :: AM.CLong
gainMute = -9999999
useLinearDbScale :: AM.CLong -> AM.CLong -> Bool
useLinearDbScale l h =
(h - l) <= maxLinearDbScale * 100
getNormalizedDb :: AM.CLong -> AM.CLong -> AM.CLong -> Int
getNormalizedDb dB low high =
let l :: Double = fromIntegral low
h :: Double = fromIntegral high
v :: Double = fromIntegral dB in
if useLinearDbScale low high
then round $ (v-l)/(h-l)*100.0
else let norm = 10.0 ** ((v - h) / 6000.0) in
if low == gainMute
then round $ norm * 100.0
else let minNorm = 10.0 ** ((l - h) / 6000.0) in
round $ (norm - minNorm) / (1 - minNorm) * 100.0
getNormalizedVal :: AM.CLong -> AM.CLong -> AM.CLong -> Int
getNormalizedVal val low high =
let v :: Double = fromIntegral val
l :: Double = fromIntegral low
h :: Double = fromIntegral high in
round $ (v - l) / (h - l) * 100.0
getNormalizedVolume :: AM.Control -> IO (Maybe Int)
getNormalizedVolume c = do
case AM.playback (AM.volume c) of
Nothing -> return Nothing
Just vol -> do
let dB = AM.dB vol
chan = head $ AM.channels dB
(lowDb, highDb) <- AM.getRangeDb vol
if lowDb >= highDb
then do (low, high) <- AM.getRange vol
if low == high
then return Nothing
else do val <- AM.getChannel chan $ AM.value vol
case val of
Nothing -> return Nothing
Just v -> return $ Just $
getNormalizedVal v low high
else do v <- AM.getChannel chan dB
case v of
Nothing -> return Nothing
Just v' -> return $ Just $
getNormalizedDb v' lowDb highDb
I created the following source code by referring to get_normalized_volume from alsa-utils/alsa-mixer/volume_mapping.c