使用 Haskell 播放 wav 文件
Posted
技术标签:
【中文标题】使用 Haskell 播放 wav 文件【英文标题】:Play a wav file with Haskell 【发布时间】:2012-12-09 22:42:07 【问题描述】:是否有一种简单、直接的方法可以使用某个库从 Haskell 播放 WAV 文件,并且可能让我一次播放多个声音?
我知道 OpenAL,但我不是在编写一些高级音频合成程序,我只是想为一些小玩意儿播放一些声音。理想情况下,API 可能类似于:
readWavFile :: FilePath -> IO Wave
playWave :: Wave -> IO ()
playWaveNonBlocking :: Wave -> IO ()
我这个接近于仅仅启动 mplayer 之类的东西。或者尝试将 wav 直接转换为 /dev/snd/ 或类似的东西。
【问题讨论】:
您可以愉快地调用第三方应用程序。 hmp3 使用mpg123 很开心。 是的。要试试这个:tivo-mplayer.sourceforge.net/docs/mplayer-man.html#sect12 对我来说足够快。 没有。指定你想要做的what 甚至都不是一件容易的事。您想跨多个操作系统进行移植吗?还是你只关心 Linux?所有 WAV 文件的采样率是否相同?还是您也需要采样率转换?声卡是多声道还是不?你需要低延迟/实时吗?或者高延迟可以吗?如果你把自己限制在 Linux 上,事情实际上会更糟……你有 OSS、Alsa、Jack 等等!当你可以有 10 种不同的方式时,为什么还要有一种播放声音的工作方式:p 【参考方案1】:这是使用 SDL 一次在多个通道上播放多个声音的方法。我认为这回答了问题标准。 WAV 文件,简单,Haskell,多通道。
import Control.Monad
import Control.Monad.Fix
import Graphics.UI.SDL as SDL
import Graphics.UI.SDL.Mixer as Mix
main = do
SDL.init [SDL.InitAudio]
result <- openAudio audioRate audioFormat audioChannels audioBuffers
classicJungle <- Mix.loadWAV "/home/chris/Samples/ClassicJungle/A4.wav"
realTech <- Mix.loadWAV "/home/chris/Samples/RealTech/A4.wav"
ch1 <- Mix.playChannel anyChannel classicJungle 0
SDL.delay 1000
ch2 <- Mix.playChannel anyChannel realTech 0
fix $ \loop -> do
SDL.delay 50
stillPlaying <- numChannelsPlaying
when (stillPlaying /= 0) loop
Mix.closeAudio
SDL.quit
where audioRate = 22050
audioFormat = Mix.Audios16LSB
audioChannels = 2
audioBuffers = 4096
anyChannel = (-1)
【讨论】:
谢谢!使用 haskell 播放音频非常困难。【参考方案2】:我意识到这实际上不是一种方便的方法,但我有测试代码,所以...
-# LANGUAGE NoImplicitPrelude #-
module Wav (main) where
import Fay.W3C.Events
import Fay.W3C.Html5
import Language.Fay.FFI
import Language.Fay.Prelude
main :: Fay ()
main = addWindowEventListener "load" run
run :: Event -> Fay Bool
run _ = do
aud <- mkAudio
setSrc aud "test.wav"
play aud
return False
mkAudio :: Fay HTMLAudioElement
mkAudio = ffi "new Audio()"
addWindowEventListener :: String -> (Event -> Fay Bool) -> Fay ()
addWindowEventListener = ffi "window['addEventListener'](%1,%2,false)"
好了——借助 HTML5 的强大功能,在 Haskell 中播放 WAV 文件!您所要做的就是启动一个网络浏览器而不是 mplayer。 :D
【讨论】:
你从哪里得到Fay.W3C.*
?
@BenMillwood:来自what the test code was testing。几天前,我在#fay 中提到过处理这些绑定,这就是引发这种半开玩笑的反应的原因。 (P.S. 对于不知道的人,Chris Done 是 Fay 的原作者。)
是的,我明白了,但代码实际上看起来也很酷:)
@BenMillwood:我破解了一个样板代码生成器,它解析 W3C 的 IDL 文件并为 Fay 生成 FFI 绑定。结果现在只有部分可用,但是如果您对它的状态感兴趣,可以在 IRC 上纠缠我。【参考方案3】:
通过 ALUT 使用 OpenAL:
import Control.Monad
import Sound.ALUT
playSound :: IO ()
playSound =
withProgNameAndArgs runALUTUsingCurrentContext $ \_ _ ->
do
(Just device) <- openDevice Nothing
(Just context) <- createContext device []
currentContext $= Just context
buffer1 <- createBuffer $ Sine 440 0 1
buffer2 <- createBuffer HelloWorld
[source] <- genObjectNames 1
queueBuffers source [buffer1,buffer2]
play [source]
sleep 4
closeDevice device
return ()
main = playSound
加载 wav 文件:
buffer3 <- createBuffer $ File "/path/to/file.wav"
感谢 Chris Double:http://bluishcoder.co.nz/articles/haskell/openal.html
【讨论】:
以上是关于使用 Haskell 播放 wav 文件的主要内容,如果未能解决你的问题,请参考以下文章