我正在编写一款Haskell命令行应用程序,可以在Linux、Windows和OS X上运行。现在我需要播放音频文件(.wav
、.ogg
和.mp3
)。我该如何实现一个函数呢?
playAudioFile :: FilePath -> IO ()
甚至更好的是
playAudio :: ByteString -> IO ()
要在所有系统上简单工作的是什么?
(我很乐意调用常见的命令行工具,也不介意将它们捆绑到Windows发行版中。)
我正在编写一款Haskell命令行应用程序,可以在Linux、Windows和OS X上运行。现在我需要播放音频文件(.wav
、.ogg
和.mp3
)。我该如何实现一个函数呢?
playAudioFile :: FilePath -> IO ()
甚至更好的是
playAudio :: ByteString -> IO ()
要在所有系统上简单工作的是什么?
(我很乐意调用常见的命令行工具,也不介意将它们捆绑到Windows发行版中。)
这是我使用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
cabal install
依赖项。SDL
,以避免依赖于未维护的 SDL-1.2 Haskell 绑定。那个代码是用C编写的,仅仅是因为随着 SDL_mixer 的示例代码几乎足够好。 - Joachim Breitnerproteaaudio
Haskell库。
ProteaAudio是一个极简的立体声音频混音/播放库,适用于Linux、MacOS和Windows操作系统。支持的音频格式包括Wav、Ogg和原始线性PCM。