将wav音频格式ByteString转换为Floats

时间:2017-01-11 20:08:30

标签: haskell audio wav data-conversion

我正在处理存储在.wav文件中的传感器数据。样本表示-1和1之间的浮点数。

我正在将.wav文件中的示例作为ByteString来读取,我需要一种方法将此ByteString转换为Float。所以我正在寻找一个具有以下签名的函数:

toFloat :: ByteString -> Float

例如。我正在使用包含1个通道的.wav文件,帧速率为48kHz,样本由24位组成。这意味着每个样本由3个字节组成,我可以从.wav文件中读取它,如下所示: hGet h 3。  这里,h是.wav文件的句柄。

如何将我从hGet获得的ByteString转换为Float(介于-1和1之间)?

正如您在previous question中看到的那样,我目前正在将ByteString转换为Double,首先将其转换为Int32(基于Data.WAVE }})。由于我的样本永远不会超过32位,我想使用Float s代替Double s。我也在寻找一种更有效的方式来进行这种转换。

修改 我目前正在将ByteString首先转换为Int32,然后转换为Double。这是由bsToDouble

完成的
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) 

作为ByteString的输入的bsToDouble直接来自hGet h 3,整数是样本中的字节数(即3)。

2 个答案:

答案 0 :(得分:3)

这样的事情会有所帮助:

getFloat

我的想法是24位值是整数,并且您希望将它们标准化为介于-1和1之间的浮点数(但排除正数1)。如果是这种情况,我认为您可以使用Data.Binary.Get和{{1}}一次解析您的信息流。

答案 1 :(得分:0)

我使用它来转换为Double,它似乎也可以帮助浮点数 - 它假设底层数字的二进制表示与内存中的表示形式相同: https://hackage.haskell.org/package/reinterpret-cast

wordToFloat :: Word32 -> Float
然而,似乎WAV中的24位将具有与您的底层平台不同的内存特性 - 如果您找到正确的尾数/指数长度,应该很容易将其转换为正确的32位浮点并使用此功能进行转换。