Андрей
Я главный автор libsndfile, а также немного хакер Хаскелла. Я посмотрел на это, и, насколько мне известно, следующий минимальный пример кода должен работать.
import qualified Sound.File.Sndfile as Snd
import Control.Applicative
import Foreign.Marshal.Array
import Data.Word (Word16)
import System.IO (hGetContents, Handle, openFile, IOMode(..))
format :: Snd.Format
format = Snd.Format Snd.HeaderFormatWav Snd.SampleFormatPcm16 Snd.EndianFile
openWavHandle :: [Word16] -> IO Snd.Handle
openWavHandle frames =
let info = Snd.Info (length frames) 441000 1 format 1 False
in Snd.openFile "temp.wav" Snd.WriteMode info
writeWav :: [Word16] -> IO Snd.Count
writeWav frames = openWavHandle frames >>= \h ->
newArray frames >>= \ptr ->
Snd.hPutBuf h ptr (length frames) >>= \c ->
return c
makeWavFile :: IO ()
makeWavFile = writeWav [1..256] >>= \c ->
putStrLn $ "Frames written: " ++ show c
main :: IO ()
main = makeWavFile
Тот факт, что он не предлагает проблемы в hsndfile. Чтобы доказать это, я взломал исходники C в libsndfile, чтобы распечатать значения структуры SF_INFO (которая hsndfile вызывает Info), и пошел так:
samplerate : 1
channels : 65538
format : 0x1
что явно не так.
Я посмотрел код hsndfile Interface.hsc. Значение для поля формата фактически заканчивается в поле каналов, а поле каналов заканчивается в поле частоты дискретизации.
Я испортил этот код, но никуда не денусь. Я отправлю ping сопровождающему hsndfile.