【发布时间】:2017-01-11 20:08:30
【问题描述】:
我正在处理存储在 .wav 文件中的传感器数据。样本代表介于 -1 和 1 之间的浮点数。
我正在以ByteStrings 的形式从.wav 文件中读取样本,我需要一种方法将这个ByteString 转换为Float。所以我正在寻找具有以下签名的函数:
toFloat :: ByteString -> Float
例如。我正在使用一个包含 1 个通道、帧速率为 48kHz 且样本由 24 位组成的 .wav 文件。这意味着每个样本包含 3 个字节,我可以从 .wav 文件中读取它,如下所示:
hGet h 3。
这里,h 是 .wav 文件的句柄。
如何将我从 hGet 获得的这个 ByteString 转换为 Float(介于 -1 和 1 之间)?
正如您在我的previous question 中看到的,我目前正在将ByteString 转换为Double,首先将其转换为Int32(基于Data.WAVE)。由于我的样本永远不会大于 32 位,因此我想使用 Floats 而不是 Doubles。我也在寻找一种更有效的方式来进行这种转换。
编辑
我目前正在将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)。
【问题讨论】:
-
您想如何将这 24 位解码为
Float?您在上一个问题中提到了Data.Binary.IEEE754。在源代码中有一个解码 16 位浮点数的示例,我希望您的 24 位需要类似的东西,然后您可以使用Data.Binary来解码您的流。 -
祝你好运,使用该库,它将样本读入嵌套链表。上次我需要这样的东西时,我开发了
wave:hackage.haskell.org/package/wave。在不知道你不切实际的目标的情况下,很难建议什么是做你想做的事情的最佳方式。 -
@Mark 我不打算使用那个库。我编写了自己的库,使用
Conduits 流式传输 .wav 文件的内容。我从库中使用的唯一部分是ByteString到Double的转换。但我正在寻找更有效的方法。 -
@ryachza 我不知道如何将这 24 位解码为
Float。那是我的问题。我不理解 16 位的示例,不足以制作我自己的 24 位版本。 -
@Mark 为什么我的最终目标对于解决这个子问题很重要?我只需要一种方法来将我的
ByteString(我从.wav 文件的数据块中读取3 个字节)转换为Float(介于-1 和1 之间)。例如。hGet给了我这个ByteString:"\131\237\242"。它应该被转换为包含-0.10212671756744385的浮点数
标签: haskell audio wav data-conversion