【问题标题】:Iterate over list in haskell?迭代haskell中的列表?
【发布时间】:2011-01-15 19:44:15
【问题描述】:

我正在使用 Portaudio 在 Haskell 中编写一个音频程序。我有一个函数可以生成我想播放的样本列表,我正在尝试在 main 中使用以下 sn-p 播放它们:

curSamps <- return (chunk 1 (sineWave 440 44100))
forever $ do
  Right numSampsAvail <- getStreamWriteAvailable paStream
  Right NoError <- writeStream paStream curSamps numSampsAvail
  curSamps <- return (drop numSampsAvail curSamps)

sineWave 是我创建的一个函数,用于以指定的频率和采样率生成无限的 Int16 正弦波样本列表。

当我调试此代码时,通过将音频输出代码替换为 putStrLn,它会打印全 0,这是该函数的第一个样本。

如何使用音频输出函数遍历此列表?我不认为我可以使用递归或映射。

编辑:代码复制错误

【问题讨论】:

  • 为什么你认为你不能使用地图?
  • 不同子表达式的值是多少? IE。什么是 take 10(sineWave 440 44100),take 10(chunk 1 (sineWave 440 44100))等等?
  • @Edward Amsden:顺便说一句,请在您之前的问题stackoverflow.com/questions/2223866/… 中留下评论,描述您是否使用 macports 安装了 portaudio。这可能对其他人有用,例如当我切换到雪豹时。谢谢:)

标签: haskell functional-programming portaudio


【解决方案1】:

使用递归:

play []       = return ()
play curSamps = do Right numSampsAvail <- getStreamWriteAvailable paStream
                   Right NoError <- writeStream paStream curSamps numSamps
                   play (drop numSampsAvail curSamps)

main = do ...
          play (chunk 1 (sineWave 440 44100))
          ...

【讨论】:

    【解决方案2】:

    考虑使用map 的一元表亲mapM/forM

    【讨论】:

    • 每个递归/循环都会从列表中删除可变数量的样本 (drop numSampsAvail)。我认为这使得使用 mapM 变得很困难。
    • @Nefrubyr:那么我们需要一个单子折叠。
    【解决方案3】:

    使用相同的 API 函数可以做到这一点:

    let playSamples curSamps = do
          Right numSampsAvail <- getStreamWriteAvailable paStream
          Right NoError <- writeStream paStream curSamps numSampsAvail
          playSamples (drop numSampsAvail curSamps)
    playSamples (chunk 1 (sineWave 440 44100))
    

    我不熟悉 Portaudio API,因此它可能会提供一种更方便、更高级的方式来完成您想要实现的目标。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-06
      • 1970-01-01
      • 2023-03-23
      • 2018-12-14
      • 1970-01-01
      • 2017-01-04
      • 2021-03-10
      相关资源
      最近更新 更多