2016-12-14 5 views
1

Ich schreibe meinen eigenen WAVE Parser, der Conduit verwendet, so dass ich Werte eins nach dem anderen durch eine Pipeline streamen kann.ByteString Darstellung einer Doppelkonvertierung

erhalte ich eine Probe aus einer .wav-Datei über hGet (n die Anzahl der Bytes pro Probe für die WAV-Datei ist):

bytes <- hGet h n

Das gibt mir eine ByteString mit einer Darstellung des Doppel Wert der Probe. Z.B .:

"\131\237\242" stellt -0.10212671756744385

"g\238\242"-0.10209953784942627

"\215\238\242" stellt -0.10208618640899658 darstellt.

Die möglichen Werte liegen zwischen -1 und +1.

Gibt es eine bequeme Möglichkeit, diese Konvertierung durchzuführen? Gibt es dafür eine Bibliothek?

Ich habe einen vorhandenen WAVE Parser für Haskell betrachtet. Data.WAVE analysiert eine .wav-Datei und gibt die Beispiele als linksbündige Int32-Werte zurück. Ich habe eine Problemumgehung gefunden, in der ich seine Bibliotheksfunktionen verwende, um meine ByteString in eine linksbündige Int32 zu konvertieren und dann in eine Double mit der sampleToDouble-Funktion der Bibliothek zu konvertieren. Das funktioniert, aber ich frage mich, ob es eine direktere Möglichkeit gibt, dieses Problem zu lösen.

Eine andere mögliche Lösung wäre es, die ByteString-[Word8] mit ByteString.unpack zu konvertieren, konvertieren [Word8]-Word32 und dann diesen Wert konvertieren zu einem Float von Data.Binary.IEEE754 die Konvertierungsfunktionen. Wäre das eine gute Lösung? Ein Problem ist, dass ich derzeit nicht weiß, wie man eine Vier-Elemente-Liste von [Word8] nach Word32 konvertiert.

+0

Haben Sie 'readDouble' in der' bytestring-lexing' Bibliothek betrachtet? – liminalisht

+1

Die sehen für mich nicht wie Hex-Zeichen aus. –

+0

@liminisht ich habe. Aber ich kann das Paket nicht installieren. Sieht so aus als hätte es bitrotten ... –

Antwort

0

Dies ist meine aktuelle Lösung, die die ByteString in ein Doppel zu drehen:

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) 

Ich frage mich, wenn dies in einer effizienteren Weise durchgeführt werden.