2016-12-14 77 views
1

我正在编写我自己的WAVE解析器,它使用Conduit,所以我可以通过管道一个接一个地传输值。ByteString表示双重转换

我通过hGet得到.wav文件的样本(n为样本的字节为wav文件数):

bytes <- hGet h n

这给了我与双的表示一个字节串样品的价值。例如: -

"\131\237\242"代表-0.10212671756744385

"g\238\242"代表-0.10209953784942627

"\215\238\242"代表-0.10208618640899658

可能的值介于-1和+1之间。

有没有方便的方法来做这种转换?有没有图书馆可以做到这一点?

我查看了现有的用于Haskell的WAVE解析器。 Data.WAVE解析.wav文件并将样本作为左对齐Int32值返回。我找到了解决方法,我使用它的库函数将ByteString转换为左对齐的Int32,然后使用库的sampleToDouble函数将其转换为Double。这有效,但我想知道是否有更直接的方法来解决这个问题。

另一种可能的解决办法是将ByteString转换为[Word8]ByteString.unpack,转换到[Word8]Word32然后该值使用转换函数从Data.Binary.IEEE754转换为Float。这会是一个很好的解决方案吗?一个问题是我目前不知道如何将[Word8]的四元素列表转换为Word32。

+0

你看过'bytestring-lexing'库中的'readDouble'吗? – liminalisht

+1

那些看起来不像我的十六进制字符。 –

+0

@liminalisht我有。但我似乎无法安装该软件包。它看起来像bitrotten ... –

回答

0

这是我目前的解决方案打开字节字符串到双:

convertNBytesLen :: [Word8] -> Int32 
convertNBytesLen = foldr accum 0 
    where accum bs a = 256 * a + fromIntegral bs 


bsToDouble :: S.ByteString -> Int -> Double 
bsToDouble bs n = if intV >= 0 
        then fromIntegral intV/2147483647 
        else - (fromIntegral intV/(-2147483648)) 
    where intV = convertNBytesLen (S.unpack bs) `shift` (32 - 8 * n) 

我不知道这是否可以以更有效的方式来完成。