pygame mixer Sound无法同时播放太多声音

我的程序想要同时播放音频,但是pygame.mixer.Sound无法同时播放太多声音。我经常按着按着就没声音了。当然,这也有可能是别的问题,如何解决呢?

这是__init__.py

mport keyboard
import threading
import time

import values

is_played_chord = False
chord_keys = {'a'}

def play_chord(bpm_time):
    global is_played_chord
    while True:
        notes = values.chordkeys.get(frozenset(chord_keys), ())
        is_played_chord = True
        for note in notes:
            values.LEFT_NOTES[note].play()
        time.sleep(bpm_time)
        for note in notes:
            values.LEFT_NOTES[note].stop()

def ask_bpm():
    try:
        return int(input("Enter your BPM: "))
    except ValueError:
        print("Please enter a number")
        return ask_bpm()
    
def on_press(key):
    global is_played_chord
    global chord_keys
    if key.name in values.RIGHT_HAND_KEYS:
        #这儿的判断是正确执行的,没有遗漏
        note = values.RIGHT_NOTES[key.name]
        #这里的stop是被迫添加的,有一点用,但不多
        note.stop()
        note.play()
    elif key.name in values.LEFT_HAND_KEYS:
        if is_played_chord:
            chord_keys = set()
            is_played_chord = False
        chord_keys.add(key.name)
    else:
        print("Unknown key {0} pressed".format(key.name))

def on_release(key):
    if key.name in values.RIGHT_HAND_KEYS:
        values.RIGHT_NOTES[key.name].stop()

def main():
    bpm_time = 60 / ask_bpm()
    keyboard.on_press(on_press)
    keyboard.on_release(on_release)
    threading.Thread(target=play_chord, args=(bpm_time,)).start()
    keyboard.wait()

if __name__ == '__main__':
    main()

这是value.py

from typing import Dict, FrozenSet, Tuple
from pygame import mixer

mixer.init()
LEFT_HAND_KEYS = {'a','s','d','f','z','x','v','q','w','e','r','1','2','3'}
RIGHT_HAND_KEYS = {'g','h','j','k','l','t','y','u','i','o','p','b','n',',','.','5','6','7','9','0'}
LEFT_NOTES = {key: mixer.Sound(f"piano/left/{key}.wav") for key in (
   'c0','d0','e0','f0','g0','a0','b0',
   'C','D','E','F','G','A','B',
   '#c0','#d0','#f0','#g0','#a0',
   '#C','#D','#F','#G','#A',
   )
}
RIGHT_NOTES = {key: mixer.Sound(f"piano/right/{key}.wav") for key in RIGHT_HAND_KEYS}

chordkeys:Dict[FrozenSet[str],Tuple[str]] = {
   frozenset({'a',}) : ("C","G","c0","e0"),
   frozenset({'s',}) : ("D","A","d0","#f0"),
   frozenset({'d',}) : ("E","B","e0","#g0"),
   frozenset({'f',}) : ("F","C","f0","a0"),
   frozenset({'q',}) : ("G","B","d0","g0"),
   frozenset({'w',}) : ("A","c0","e0","a0"),
   frozenset({'e',}) : ("B","#d0","#f0","b0"),
   frozenset({'r',}) : ("C","G","c0","e0"),
}

以下回答参考GPT,请查看是否可以解决你的问题:
您遇到的问题可能是由于pygame.mixer.Sound无法同时播放太多声音导致的。这是因为在pygame.mixer.Sound中,每个声音都需要独立的声道,如果同时播放太多声音,声道可能不足,导致一些声音被静音或丢失。

为了解决这个问题,可以考虑使用pygame.mixer.music模块来实现同时播放多个声音。相比于pygame.mixer.Soundpygame.mixer.music能够更好地处理同时播放多个声音的情况。

以下是对您提供的代码进行修改的示例:

import keyboard
import threading
import time
import pygame.mixer

import values

is_played_chord = False
chord_keys = {'a'}

def play_chord(bpm_time):
    global is_played_chord
    while True:
        notes = values.chordkeys.get(frozenset(chord_keys), ())
        is_played_chord = True
        for note in notes:
            pygame.mixer.music.load(values.LEFT_NOTES[note])
            pygame.mixer.music.play()
        time.sleep(bpm_time)
        pygame.mixer.music.stop()

def ask_bpm():
    try:
        return int(input("Enter your BPM: "))
    except ValueError:
        print("Please enter a number")
        return ask_bpm()

def on_press(key):
    global is_played_chord
    global chord_keys
    if key.name in values.RIGHT_HAND_KEYS:
        note = values.RIGHT_NOTES[key.name]
        note.stop()
        note.play()
    elif key.name in values.LEFT_HAND_KEYS:
        if is_played_chord:
            chord_keys = set()
            is_played_chord = False
        chord_keys.add(key.name)
    else:
        print("Unknown key {0} pressed".format(key.name))

def on_release(key):
    if key.name in values.RIGHT_HAND_KEYS:
        values.RIGHT_NOTES[key.name].stop()

def main():
    bpm_time = 60 / ask_bpm()
    keyboard.on_press(on_press)
    keyboard.on_release(on_release)
    threading.Thread(target=play_chord, args=(bpm_time,)).start()
    keyboard.wait()

if __name__ == '__main__':
    pygame.mixer.init()
    main()

在修改后的代码中,我添加了pygame.mixer.init()来初始化音频模块,并且使用了pygame.mixer.music来同时播放多个声音。注意,在使用pygame.mixer.music时,需要确保音频文件的路径是正确的。

请注意,由于我无法运行完整的代码并测试它,在实际运行中可能会遇到其他问题。如果您仍然遇到困难,请提供更多的细节和错误信息,以便我能够更好地帮助您解决问题。

【相关推荐】



  • 这篇博客: 使用pygame播放音频中的 pygame.mixer.music模块的函数: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    1. pygame.mixer.music.load() 加载音乐。参数为filename,以字符串传入音频文件地址;
    2. pygame.mixer.music.unload() 卸载已经加载的音乐。无参数;
    3. pygame.mixer.music.play() 播放加载的音乐。三个可选参数,loops循环次数(int);start开始播放时间(float)有的文件类型可能不支持(我试验过的Ubuntu环境下wav文件不支持设置)mp3文件的时间定位可能不准确;fade_ms音量渐变的时间间隔(int)我没有听出啥区别。。。;这三个参数默认为0
    4. pygame.mixer.music.rewind() 重新开始音乐。
    5. pygame.mixer.music.stop() 停止音乐播放。
    6. pygame.mixer.music.pause() 暂停音乐播放。
    7. pygame.mixer.music.unpause() 恢复暂停的音乐。
    8. pygame.mixer.music.fadeout() 淡出后停止音乐播放。
    9. pygame.mixer.music.set_volume() 设置音量。参数0~1之间的浮点数;
    10. pygame.mixer.music.get_volume() 获得音量。返回一个浮点数(0~1之间);
    11. pygame.mixer.music.get_busy() 音乐是否播放。返回一个bool类型的值(文档的说明)我实际测试返回的是0和1不过无所谓当需要传bool值是python会将1看成True0,看成False的(Ubuntu环境)。我的测试程序及结果如下:
    import pygame
    
    pygame.mixer.init()
    pygame.mixer.music.load('1.wav')
    pygame.mixer.music.play()
    print(pygame.mixer.music.get_busy()) # 打印返回值
    print(type(pygame.mixer.music.get_busy())) # 打印返回值类型
    

    结果:
    在这里插入图片描述

    1. pygame.mixer.music.set_pos() 设定位置(开始播放的位置)。参数pos(float),有的文件类型可能不支持详细见文档。
    2. pygame.mixer.music.get_pos() 获取音乐播放时间(注意这是已经播放的时间不是音乐时间长度)。返回播放的毫秒数;
    3. pygame.mixer.music.queue() 将声音文件排队以跟随当前文件(意思是在当前播放的声音后面再加上声音一次只能加一个,如果当前的声音未播放完就停止则后面加的声音也将丢失)。参数filename,以字符串传入音频文件地址;
      示例:
    pygame.mixer.music.load('所谓当前音频')
    pygame.mixer.music.play()       
    pygame.mixer.music.queue('添加的音频') # 这个音频会在当前音频播放完后播放
    
    1. pygame.mixer.music.set_endevent() 播放停止时让音乐发送事件
    2. pygame.mixer.music.get_endevent() 获取播放停止时频道发送的事件

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

可以通过pygame.mixer.set_num_channels(count)设置声道的数量
声道的数量决定了同时播放声音的个数,默认的声道数量为8,如果声道数量越多就能同时播放更多的声音
例如:

pygame.mixer.set_num_channels(99) # 可同时播放99个声音

然后通过Sound.play播放声音
https://blog.csdn.net/qq_48979387/article/details/129219749