Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何从Haskell代码跨平台播放音频文件_Linux_Windows_Haskell_Audio - Fatal编程技术网

Linux 如何从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

我正在编写一个在Linux、Windows和OS X上运行的Haskell命令行应用程序。我现在必须从中播放音频文件(
.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克隆这个要点。