linux 如何从Haskell代码中播放音频文件,跨平台

4ioopgfo  于 2023-08-03  发布在  Linux
关注(0)|答案(2)|浏览(82)

我正在编写一个Haskell命令行应用程序,可以在Linux、Windows和OSX上运行。我现在必须从它播放音频文件(.wav.ogg.mp3)。我该如何实现一个函数

playAudioFile :: FilePath -> IO ()

字符串
甚至更好

playAudio :: ByteString -> IO ()


在所有系统上都能正常工作
(我很乐意调用常见的命令行工具,也不介意将它们捆绑到Windows发行版中。

km0tfn4u

km0tfn4u1#

这是我使用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

字符串
程序最终运行良好,但是

  • 在Windows下编译SDL绑定是很棘手的。我关注了this nice explanation on how to do it
  • SDL-1.2的SDL绑定似乎是未维护的和do not even compile with GHC-7.8 or newer。起初我没有注意到,因为我的发行版(Debian)围绕这些问题打了补丁,但这意味着我的用户再也不能轻松地cabal install依赖项了。
  • 有SDL-2的绑定,但没有SDL_mixer的绑定,我在这里需要(我相信)。

所以我会很高兴地读到更好的答案。

qlfbtfca

qlfbtfca2#

一个新的选项是proteaaudio Haskell库:
https://hackage.haskell.org/package/proteaaudio
ProteaAudio是一个极简主义的立体声音频混音器/播放库

  • Linux操作系统
  • MacOS
  • windows

支持的音频格式:

  • 瓦夫
  • 奥格
  • 原始线性脉码调制

相关问题