异步并发地播放不同音高的声音

2024-03-30

我的目标是使用 Python 在计算机游戏环境中播放满足以下要求的声音。

  1. 获取一些输入 WAV 文件并随机将音高改变为原始值的 +/- 50%。使用 PyDub 更改采样率似乎是一种简单的方法。

  2. 播放声音。

  3. 能够快速调用该函数,使实际播放时长短声音重叠。

我花了超过 24 个工作时间来寻找满足所有这些要求的方法。我以前曾在 Visual Basic 中完成过此操作,并且对 Python 中的难度感到惊讶。

到目前为止我所知道的是:

  1. PyGame.Mixer 可以同时播放重叠的声音,但是它must以相同的采样率播放它们。似乎没有办法改变音调。

  2. PyDub 可以通过改变采样率来改变音调,但它无法通过其基本播放来播放重叠的声音。而且,我必须将输出声音写入文件,然后立即将其加载回来,这感觉很浪费。

  3. WinSound 可以播放 PyDub 的可变采样率声音,但不能并发播放,甚至不能使用线程。

  4. Playsound 包不适用于 python 3.6。

  5. 如果我使用线程,PyAudio 可以通过并发播放来播放 PyDub 的可变采样率声音,但是,如果使用次数超过几次,就会导致可怕的内存问题,很快就会导致 Python 崩溃。

我的问题:如何在不造成问题的情况下实现上述 3 个目标?

这是迄今为止我得到的最好结果(这是 PyAudio 版本,如果测试超过一次或两次,则会导致崩溃):

from pydub import AudioSegment
from random import random, seed
from time import sleep
import os
import threading
import pyaudio
import wave

def PlayAsyncWithRandPitch(WavPath):
    MyBaseFilename = os.path.basename(WavPath)
    sound = AudioSegment.from_file(WavPath, format="wav")
    seed()
    octaves = ((random()-0.50))
    print("random octave factor for this sound is: "+str(octaves))
    print("current sound frame rate:"+str(sound.frame_rate))
    new_sample_rate = int(sound.frame_rate * (2.0 ** octaves))
    print("new sound frame rate:"+str(new_sample_rate))
    newpitchsound = sound._spawn(sound.raw_data, overrides={'frame_rate': new_sample_rate})
    MyTotalNewPath = os.getcwd()+"\\Soundfiles\\Temp\\Mod_"+MyBaseFilename
    newpitchsound.export(MyTotalNewPath, format="wav")
    SoundThread = threading.Thread(target=PAPlay, args=(MyTotalNewPath,))
    SoundThread.start()
#=======================================================================================


#This function is just code for playing a sound in PyAudio
def PAPlay(filename):
    CHUNK = 1024
    wf = wave.open(filename, 'rb')
    p = pyaudio.PyAudio()
    stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                    channels=wf.getnchannels(),
                    rate=wf.getframerate(),
                    output=True)
    data = wf.readframes(CHUNK)
    while data != '':
        stream.write(data)
        data = wf.readframes(CHUNK)
    stream.stop_stream()
    stream.close()
    p.terminate()
    return


if __name__ == "__main__":
    #Example sounds to test if more than one can play at once
    PlayAsyncWithRandPitch(os.getcwd()+'\\Soundfiles\\RifleMiss.WAV')
    sleep(0.2)
    PlayAsyncWithRandPitch(os.getcwd()+'\\Soundfiles\\splash.wav')
    sleep(0.2)
    PlayAsyncWithRandPitch(os.getcwd()+'\\Soundfiles\\sparkhit1.WAV')
    sleep(5.0)

预先感谢您的帮助!


多亏了又一个小时的谷歌搜索,我找到了一个关于 PyDub 的晦涩注释来解决这个问题。有一种方法可以实际更改采样率,但“实际上”不能更改采样率。这就是所谓的花栗鼠方法。

https://github.com/jiaaro/pydub/issues/157#issuecomment-252366466 https://github.com/jiaaro/pydub/issues/157#issuecomment-252366466

我真的不想假装理解这里的细微差别,但似乎这个概念是“发出声音,set将采样率更改为某个修改值,然后convert采样率回到传统的 44,100 HZ 值。”

他们给出了这个非常有效的例子:

from pydub import AudioSegment
sound = AudioSegment.from_file('./test/data/test1.mp3')
# shift the pitch up by half an octave (speed will increase proportionally)
octaves = 0.5
new_sample_rate = int(sound.frame_rate * (2.0 ** octaves))
# keep the same samples but tell the computer they ought to be played at the 
# new, higher sample rate. This file sounds like a chipmunk but has a weird sample rate.
chipmunk_sound = sound._spawn(sound.raw_data, overrides={'frame_rate': new_sample_rate})
# now we just convert it to a common sample rate (44.1k - standard audio CD) to 
# make sure it works in regular audio players. Other than potentially losing audio quality (if
# you set it too low - 44.1k is plenty) this should now noticeable change how the audio sounds.
chipmunk_ready_to_export = chipmunk_sound.set_frame_rate(44100)

这对我来说没有多大意义,但它确实有效:)希望这对那里的人有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

异步并发地播放不同音高的声音 的相关文章

随机推荐

  • 贝叶斯网络与 R

    我正在尝试建立贝叶斯网络模型 但是我无法安装合适的软件包 尝试过gRain bnlearn and Rgraphviz用于绘图 我在 R 2 15 和 3 2 中尝试过 以下是错误消息 library gRain Loading requi
  • Jquery .click 不触发

    尝试在这里学习 JQuery 一开始非常简单 当我单击该按钮时 页面会重新加载 但什么也没有发生 这是我的 JS 这是我的html div class panel right div
  • Oracle 位和函数

    我对 oracle bitand 功能感到困惑 我知道它用于控制是否设置两位 但是 被设定的意义何在 何时以及为何使用它 如果你能给出一个基于真实例子的例子 我会很高兴 感谢您的回答 在二进制中 set 的意思是 值为 1 未设置 意味着
  • KnpSnappyBundle 和 Symfony 3.4:图像和/或 css 导致超时

    我已经在现有的 Symfony 3 4 项目上安装了 KnpSnappyBundle 我已经用 HTML 树枝测试了 PDF 生成器 仅包含文本 没有图像 没有 css 没有 js 它工作正常 然后我使用绝对 URL 添加 到树枝 图像和
  • MySQL Select...用于更新索引存在并发问题

    这是我上一个问题的后续问题 您可以跳过它 因为我在这篇文章中解释了该问题 MySQL InnoDB SELECT LIMIT 1 FOR UPDATE 与 UPDATE LIMIT 1 https stackoverflow com que
  • 在多个数据库上实现事务

    我正在对多个数据库执行数据更改 并且我想实现一个涵盖所有更改的事务 这就是我目前所拥有的 try db 1 begintransaction db 1 ExecuteNonQuery db 2 begintransaction db 2 E
  • perl 从文件中删除行

    我的文件看起来像 ATOM 2517 O VAL 160 8 337 12 679 2 487 ATOM 2518 OXT VAL 160 7 646 12 461 0 386 TER ATOM 2519 N VAL 161 14 431
  • InversifyJS @multiInject 不起作用,抛出错误“发现 serviceIdentifier 不明确匹配”

    我在我的打字稿项目中使用 inversifyJs 进行 DI 使用装饰器 multiInject 时 我收到错误 发现 serviceIdentifier 不明确匹配 我正在遵循这个例子 https github com inversify
  • 如何关闭 Sublime Text 2 中某些文件的删除空格功能?

    我有一个选择trim trailing white space on save打开 对于某些文件 我应该防止删除尾随空格 因为它们很重要 如何删除某些文件的此行为 例如 dat 您是否已尝试为该特定扩展创建配置文件并放置trim trail
  • 如何链接到页面并使用 Rails 激活特定选项卡

    如果信息页面具有基于不同主题的多个选项卡 并且存在从不同页面通向信息页面的链接 那么如何根据所使用的链接链接到具有活动选项卡的信息页面 我想要一个像这样的链接 p View the terms conditions on our info
  • 将季度数据框转换为每月数据框并填充 Pandas 中的缺失值

    对于这样的季度数据框 date gdp rate 0 2003 3 1 523 82 0 1 1 2003 6 1 1172 83 0 2 2 2003 9 1 1882 48 0 4 3 2003 12 1 3585 72 0 1 4 2
  • 如何将即时时间转换为本地时间?

    即使阅读了大量教程后 我也不太了解 TemporalAdjusters 或 Java 的新时间库 我怎样才能转换Instant反对LocalTime目的 我正在思考以下内容 LocalTime time LocalTime of insta
  • Eclipse Hibernate.cfg.xml 正在从 MySQL 链接“sys”数据库

    当我使用 Hibernate 连接 MySQL 数据库时 书库数据库 在 Eclipse 中 连接到 MySQLsys数据库也显示出来了 我正在使用以下内容 Ubuntu 18 04 5 LTS 桌面 Eclipse 2020 6 4 16
  • Java Http 客户端通过 POST 上传文件

    我正在开发一个 J2ME 客户端 它必须使用 HTTP 将文件上传到 Servlet servlet 部分使用 Apache Commons FileUpload 进行覆盖 protected void doPost HttpServlet
  • 追加函数不返回追加的对象吗?

    假设this是 dom 中一些现有的块级元素 image is http www google com images srpr nav logo25 png执行以下操作不起作用 this append img attr src image
  • boost::asio 无法完全关闭 TCP 连接

    我正在尝试实现一个简单的 HTTP 服务器 我能够向客户端发送 HTTP 响应 但问题是在 Firefox 上我收到 连接重置 错误 IE 也失败了 而 Chrome 工作正常并显示我在响应中发送的 HTML 如果我远程登录到我的服务器 那
  • 如何从 UI 测试访问我的 swift 类?

    我有一个像这样的 UI 测试 func testHome if isRedOrange clear code 如何从 UI 测试中的 isRedOrange swift 文件访问 isRedOrange clear 函数 UI 测试是黑盒的
  • 隐藏预期输出

    这是期望脚本的一部分 usr bin expect spawn noecho kwalletcli f Passwords e keyofmypassword expect set passwd expect out buffer do s
  • 当我使用 discord.py 使用 ast.literal_eval 时,第 1 行出现格式错误的节点或字符串

    我尝试执行 import ast ast literal eval 5 5 然后我得到了ValueError malformed node or string on line 1
  • 异步并发地播放不同音高的声音

    我的目标是使用 Python 在计算机游戏环境中播放满足以下要求的声音 获取一些输入 WAV 文件并随机将音高改变为原始值的 50 使用 PyDub 更改采样率似乎是一种简单的方法 播放声音 能够快速调用该函数 使实际播放时长短声音重叠 我