本文介绍了如何从跨平台的Haskell代码播放音频文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在编写一个可在Linux,Windows和OS X上运行的Haskell命令行应用程序.现在,我必须从中播放音频文件(.wav
,.ogg
和.mp3
).我将如何实现功能
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. How would I go about implementing a function
playAudioFile :: FilePath -> IO ()
甚至更好
playAudio :: ByteString -> IO ()
在所有系统上都能正常工作吗?
that simply works on all system?
(我很高兴调用常见的命令行工具,并且不介意将它们捆绑到Windows发行版中.)
(I’m happy to invoke common command line tools and also don’t mind bundling them for the Windows distribution.)
推荐答案
这是我使用SDL-1.2想到的代码:
This is the code I came up with, using 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
- 在Windows下编译SDL绑定非常棘手.我遵循了关于此操作的很好的解释
- 似乎未维护SDL-1.2的SDL绑定,并且不会甚至可以使用GHC-7.8或更高版本进行编译.起初我没有注意到,因为我的发行版(Debian)围绕此类问题进行了修补,但这意味着我的用户不再容易
cabal install
依赖项. - 有SDL-2的绑定,但没有SDL_mixer的绑定,我在这里需要(我相信).
- compiling the SDL bindings under Windows is tricky. I followed this nice explanation on how to do it
- the SDL bindings for SDL-1.2 seem to be unmaintained and do not even compile with GHC-7.8 or newer. I didn’t notice at first, because my distribution (Debian) patches around such issues, but it means that my users cannot easily
cabal install
the dependencies any more. - there are bindings for SDL-2, but none for the SDL_mixer, which I need here (I believe).
所以我会很高兴阅读更好的答案.
So I’ll happily read better answers.
这篇关于如何从跨平台的Haskell代码播放音频文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!