Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 通过TestRing将wav音频格式转换为浮点数_Haskell_Audio_Wav_Data Conversion - Fatal编程技术网

Haskell 通过TestRing将wav音频格式转换为浮点数

Haskell 通过TestRing将wav音频格式转换为浮点数,haskell,audio,wav,data-conversion,Haskell,Audio,Wav,Data Conversion,我正在处理存储在.wav文件中的传感器数据。这些示例表示介于-1和1之间的浮点数 我正在以ByteStrings的形式从.wav文件中读取样本,我需要一种方法将此ByteString转换为Float。因此,我正在寻找一个具有以下签名的函数: toFloat::ByteString->Float 比如说。我正在使用一个.wav文件,它包含一个通道,帧速率为48kHz,样本由24位组成。这意味着每个示例由3个字节组成,我可以从.wav文件中读取它,如下所示: hGet h3。 这里,h是.wav文件

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

我正在以
ByteString
s的形式从.wav文件中读取样本,我需要一种方法将此
ByteString
转换为
Float
。因此,我正在寻找一个具有以下签名的函数:

toFloat::ByteString->Float

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

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

正如您在my中所看到的,我当前正在通过将
ByteString
转换为
双精度
,方法是首先将其转换为
Int32
(基于)。由于我的示例从不大于32位,因此我希望使用
Float
s而不是
Double
s。我也在寻找一种更有效的转换方法

编辑 我目前正在通过testring将
转换为
Int32
,然后再转换为
Double
。这是通过
bstoduble
完成的:

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) 

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

我正在使用它来转换为
双精度
,它似乎也可以帮助处理浮点数-它假定基础数字的二进制表示形式与内存中的表示形式相同:


然而,似乎WAV中的24位与底层平台的内存特性不同-如果找到正确的尾数/指数长度,将其转换为适当的32位浮点并使用此函数进行转换应该非常容易。

我使用此函数将其转换为
Double
,它似乎也能帮助处理浮点数-它假定基础数字的二进制表示形式与内存中的表示形式相同:


然而,似乎WAV中的24位与您的底层平台具有不同的内存特性-如果您找到了正确的尾数/指数长度,那么将其转换为适当的32位浮点并使用此函数进行转换应该非常容易。

执行类似于以下帮助的操作:

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)。如果是这种情况,我想您可以将
getFloat
Data.Binary.Get
一起使用,一次解析24位的流。

这样做有助于:

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)。如果是这种情况,我想您可以使用
getFloat
Data.Binary.Get
一次解析24位流。

如何将这24位解码为
Float
?您在上一个问题中提到了
Data.Binary.IEEE754
。在源代码中有一个解码16位浮点的示例,我希望您的24位需要类似的东西,然后您可以使用
Data.Binary
对流进行解码。祝您使用该库好运,它会将样本读取到嵌套的链接列表中。上次我需要这样的东西时,我开发了
wave
:。如果不知道你的目标是什么,你很难建议什么是做你想做的事情的最佳方式。@Mark我不打算使用这个库。我已经编写了自己的库,它使用
conduct
s对.wav文件的内容进行流式处理。我从库中使用的唯一部分是
ByteString
Double
的转换。但我正在寻找更有效的方法。@ryachza我不知道如何将这24位解码为
浮点值。那是我的问题。我不理解16位的例子,不足以制作我自己的24位版本。@马克,为什么我的最终目标对解决这个子问题很重要?我只需要一种方法将我的
转换为testring
,从.wav文件的数据块读取3个字节,转换为
浮点值(介于-1和1之间)。例如,
hGet
通过testring给我这个
“\131\237\242”
。应将其转换为包含
-0.10212671756744385
的浮点,您希望如何将这24位解码为
浮点
?您在上一个问题中提到了
Data.Binary.IEEE754
。在源代码中有一个解码16位浮点的示例,我希望您的24位需要类似的东西,然后您可以使用
Data.Binary
对流进行解码。祝您使用该库好运,它会将样本读取到嵌套的链接列表中。上次我需要这样的东西时,我开发了
wave
:。如果不知道你的目标是什么,你很难建议什么是做你想做的事情的最佳方式。@Mark我不打算使用这个库。我已经编写了自己的库,它使用
conduct
s对.wav文件的内容进行流式处理。我从库中使用的唯一部分是
ByteString
Double
的转换。但我正在寻找更有效的方法。@ryachza我不知道如何将这24位解码为
浮点值。那是我的问题。我不理解16位的例子,不足以制作我自己的24位版本。@马克,为什么我的最终目标对解决这个子问题很重要?我只需要一种方法将我的
转换为testring
,从.wav文件的数据块读取3个字节,转换为
浮点值(介于-1和1之间)。例如: