【问题标题】:Generating sine wave sound in Python在 Python 中生成正弦波声音
【发布时间】:2012-01-08 02:47:33
【问题描述】:

我需要在 Python 中生成正弦波声音,并且我需要能够控制频率、持续时间和相对音量。 “生成”是指我希望它立即通过扬声器播放,而不是保存到文件中。

最简单的方法是什么?

【问题讨论】:

标签: python audio


【解决方案1】:

在 Python 中处理声音的一种更一致且易于安装的方法是 Pygame 多媒体库。

我建议使用它 - pygame.sndarray 子模块允许您操作数据向量中的数字,这些数字成为可以在 pygame.mixer 模块中播放的高级声音对象。

pygame.org 站点中的文档应该足以使用 sndarray 模块。

【讨论】:

    【解决方案2】:

    bregman lab toolbox 拥有一组完全符合您要求的功能。这个 python 模块有一点问题,但你可以修改这段代码来获得你自己的功能

    【讨论】:

      【解决方案3】:
      import pyaudio
      import numpy as np
      
      p = pyaudio.PyAudio()
      
      volume = 0.5     # range [0.0, 1.0]
      fs = 44100       # sampling rate, Hz, must be integer
      duration = 1.0   # in seconds, may be float
      f = 440.0        # sine frequency, Hz, may be float
      
      # generate samples, note conversion to float32 array
      samples = (np.sin(2*np.pi*np.arange(fs*duration)*f/fs)).astype(np.float32)
      
      # for paFloat32 sample values must be in range [-1.0, 1.0]
      stream = p.open(format=pyaudio.paFloat32,
                      channels=1,
                      rate=fs,
                      output=True)
      
      # play. May repeat with different volume values (if done interactively) 
      stream.write(volume*samples)
      
      stream.stop_stream()
      stream.close()
      
      p.terminate()
      

      【讨论】:

      • 我发现@yahweh 的贡献确实如此。包含在代码示例中会很有帮助。
      • 这在我的 Linux 系统上不起作用,它在播放完所有样本之前就中断了,例如持续时间 2 它播放不到一秒。我使用回调方法播放所有样本。完整示例:gist.github.com/FrankBuss/3c2f0d1eaf289ef9f659139b96e7a459
      • 对我来说听起来不像正弦波!
      • 寻找没有numpy依赖的版本。
      【解决方案4】:

      今天对于 Python 3.5+ 最好的方法是安装开发者推荐的包。

      http://people.csail.mit.edu/hubert/pyaudio/

      对于 Debian 做

      sudo apt-get install python3-all-dev portaudio19-dev
      

      在尝试安装 pyaudio 之前

      【讨论】:

        【解决方案5】:

        ivan-onys 给出了一个很好的答案,但还有一点补充: 此脚本将产生比预期短 4 倍的声音,因为 Pyaudio 写入方法需要 float32 的字符串数据,但是当您将 numpy 数组传递给此方法时,它将整个数组作为实体转换为字符串,因此您必须将 numpy 数组中的数据转换为自己的字节序列是这样的:

        samples = (np.sin(2*np.pi*np.arange(fs*duration)*f/fs)).astype(np.float32).tobytes()
        

        你也必须改变这一行:

        stream.write(samples)
        

        【讨论】:

        • 非常有趣@yahweh。这解决了我遇到的另一个问题。你能告诉我为什么 .tobytes() 解决了这个问题吗?
        【解决方案6】:

        来自 ivan_onys 的脚本产生的信号比预期的短四倍。如果卷为浮点数时返回 TypeError,请尝试将 .tobytes() 添加到以下行。

        stream.write((volume*samples).tobytes())
        

        @mm_float32 = 32 位,8 位 = 1 字节,所以 float32 = 4 字节。当样本作为 float32 传递给 stream.write 时,字节数(持续时间)除以 4。将样本写回 .tobytes() 可纠正在写入 float32 时将样本数四等分。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-01-27
          • 1970-01-01
          • 1970-01-01
          • 2021-05-13
          • 1970-01-01
          • 2012-07-11
          • 1970-01-01
          相关资源
          最近更新 更多