Linux 如何从Haskell代码跨平台播放音频文件
我正在编写一个在Linux、Windows和OS X上运行的Haskell命令行应用程序。我现在必须从中播放音频文件(Linux 如何从Haskell代码跨平台播放音频文件,linux,windows,haskell,audio,Linux,Windows,Haskell,Audio,我正在编写一个在Linux、Windows和OS X上运行的Haskell命令行应用程序。我现在必须从中播放音频文件(.wav、.ogg和.mp3)。我如何实现一个函数 playAudioFile :: FilePath -> IO () 甚至更好 playAudio :: ByteString -> IO () 这对所有系统都有效吗 (我很乐意调用常用的命令行工具,也不介意将它们绑定到Windows发行版。)这是我使用SDL-1.2编写的代码: module PlaySound
.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
模块播放声音(带声音,播放声音),其中
进口管制
导入系统.IO
导入系统目录
导入数据。可折叠
导入控制。异常
将限定数据.ByteString.Lazy作为B导入
进口外国货
将Graphics.UI.SDL导入为SDL
将Graphics.UI.SDL.Mixer作为Mix导入
使用声音::IO a->IO a
withSound=括号uuu初始清理
哪里
init=do
SDL.init[SDL.InitAudio]
getError>>=遍历
ok IO()
播放声音内容=do
这与dir有关,但除了.wav
,我还需要播放常见的文件格式。如果这真的可行,我会(高兴地)感到惊讶。我的意思是,没有手动编写绑定到一些现有的C库自己…嗯,可能实际上指向了正确的方向;SDL似乎在中支持MP3和Ogg。gstreamer在OSX、Windows和Linux上运行,并支持许多不同的格式,因此这可能值得一看。我有点担心从中获得一个友好的、独立的Windows软件包,但至少这是可能的。最后,我使用了一个专用的二进制文件SDL
,避免对SDL-1.2 Haskell绑定(未维护)的依赖。这仅仅是因为SDL_混音器附带的示例代码几乎已经足够好了。我认为最好有一种简单的方式来播放MP3或WAV,而不需要SDL和SDL_混音器,或者至少隐藏这些细节。我刚刚向SDL_mixer的维护人员发送了一个补丁,让其使用GHC 7.8进行编译(这给了我一个链接错误)。我很好奇:你有什么问题?混合器有SDL2绑定,请参阅。我用这些做了Keera工作室的魔法饼干!它们工作得很好(只做了一些小的调整,以便为Android编译它们)。我不记得了,但可能与中提到的相同。关于sd2 mixer
:这还没有出现在hackage上,这一定阻止了我使用它们。sdl mixer的新版本(sdl 1.2)现在正在出现在hackage上:我可以验证它是否与GHC 7.8一起工作。如果它对任何人都有帮助,举个简单的例子,用git克隆这个要点。