[英]How to play an audio file from Haskell code, cross-platform
I'm writing a Haskell command line application that runs on Linux, Windows and OS X. I now have to play audio files ( .wav
, .ogg
and .mp3
) from it. 我正在编写一个在Linux,Windows和OS X上运行的Haskell命令行应用程序。我现在必须从中播放音频文件(
.wav
, .ogg
和.mp3
)。 How would I go about implementing a function 我将如何实现一个功能
playAudioFile :: FilePath -> IO ()
or even better 甚至更好
playAudio :: ByteString -> IO ()
that simply works on all system? 只是适用于所有系统?
(I'm happy to invoke common command line tools and also don't mind bundling them for the Windows distribution.) (我很高兴调用常见的命令行工具,也不介意将它们捆绑为Windows发行版。)
This is the code I came up with, using SDL-1.2: 这是我提出的代码,使用SDL-1.2:
module PlaySound (withSound, playSound) where
import Control.Monad
import System.IO
import System.Directory
import Data.Foldable
import Control.Exception
import qualified Data.ByteString.Lazy as B
import Foreign.ForeignPtr
import Graphics.UI.SDL as SDL
import Graphics.UI.SDL.Mixer as Mix
withSound :: IO a -> IO a
withSound = bracket_ init cleanup
where
init = do
SDL.init [SDL.InitAudio]
getError >>= traverse_ putStrLn
ok <- Mix.tryOpenAudio Mix.defaultFrequency Mix.AudioS16LSB 2 4096
unless ok $
putStrLn "Failed to open SDL audio device"
cleanup = do
Mix.closeAudio
SDL.quit
playSound :: B.ByteString -> IO ()
playSound content = do
dir <- getTemporaryDirectory
(tmp, h) <- openTempFile dir "sdl-input"
B.hPutStr h content
hClose h
mus <- Mix.loadMUS tmp
Mix.playMusic mus 1
wait
-- This would double-free the Music, as it is also freed via a
-- finalizer
--Mix.freeMusic mus
finalizeForeignPtr mus
removeFile tmp
wait :: IO ()
wait = do
SDL.delay 50
stillPlaying <- Mix.playingMusic
when stillPlaying wait
The program in the end works fine, but 该程序最终工作正常,但是
cabal install
the dependencies any more. cabal install
依赖项。 So I'll happily read better answers. 所以我很乐意阅读更好的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.