haskell - 将 wav 音频格式 ByteString 转换为 Floats

标签 haskell audio wav data-conversion

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

我正在从 .wav 文件中读取样本为 ByteString s,我需要一种方法来转换此 ByteStringFloat .所以我正在寻找具有以下签名的函数:
toFloat :: ByteString -> Float
例如。我正在处理一个包含 1 个 channel 的 .wav 文件,帧率为 48kHz,样本由 24 位组成。这意味着每个样本由 3 个字节组成,我可以从 .wav 文件中读取它,如下所示:hGet h 3 .
在这里,h是 .wav 文件的句柄。

如何转换我从 hGet 获得的这个 ByteString到 Float (在 -1 和 1 之间)?

正如你在我的 previous question 中看到的,我目前正在转换 ByteStringDouble首先将其转换为 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)。

最佳答案

这样的事情有帮助吗:

import Data.Int (Int32)
import Data.Bits ((.|.),(.&.),unsafeShiftL)
import Data.Word (Word32)
import Data.Binary
import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BSU

int32_24be :: BS.ByteString -> Int32
int32_24be = \s ->
  let x =   unsafeShiftL (fromIntegral (BSU.unsafeIndex s 0)) 16
        .|. unsafeShiftL (fromIntegral (BSU.unsafeIndex s 1))  8
        .|.               fromIntegral (BSU.unsafeIndex s 2)
        :: Int32
      y = fromIntegral x :: Word32
  in fromIntegral (if x .&. 0x00800000 > 0 then y .|. 0xFF000000 else y .&. 0x00FFFFFF)

getFloat :: BS.ByteString -> Float
getFloat = (/ 2^^23) . fromIntegral . int32_24be

我的想法是 24 位值是整数,您希望将它们标准化为 -1 和 1 之间的浮点数(不过,正 1 除外)。如果是这种情况,我想您可以使用 getFloatData.Binary.Get一次解析您的流 24 位。

关于haskell - 将 wav 音频格式 ByteString 转换为 Floats,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41599845/

相关文章:

haskell - 当我尝试返回列表时出错

audio - 链接以强制将MP3文件下载到默认下载文件夹

flash - 如何使用http播放wave文件?

c++ - SDL_mixer WAVE 音频格式质量差

java :健全的交通问题

haskell - Haskell 中的惯用向量代数

haskell - 没有包装值(value)的单子(monad)?

haskell - 设计基本的 Haskell 基准测试代码

c# - 多次播放相同的声音 C# WPF

c++ - 为什么录制的音频数据仅使用缓冲区的一半(WaveIn)?