Pygame - Sound delay

2020-02-10 07:23发布

I've made a button class that checks if a button is selected (when the mouse is hovering over the button). When the button is selected, unselected or clicked it plays a wav file. The problem is that there is a huge delay between the sound playing and the button's state changing. The program should check every frame to see if the conditions for the sound to play have been met but the fps doesn't seem to be the problem (60 and 600 fps give the same delay). I've tried decreasing the buffer value in pygame.mixer.init() but that also shows no difference.

Sound files:

buttonSoundSelect = pygame.mixer.Sound(os.path.join(soundPath, "button1.wav"))
buttonSoundUnselect = pygame.mixer.Sound(os.path.join(soundPath, "button2.wav"))
buttonSoundClick = pygame.mixer.Sound(os.path.join(soundPath, "button3.wav"))
buttonSounds = [buttonSoundSelect, buttonSoundUnselect, buttonSoundClick]

Creating the object:

playButton = button(textInactive = "Play", font = mainFont, sounds = buttonSounds,  command = playAction)

Code from the button class that checks if the button is selected (this is inside the method .display which is called every frame):

    if pygame.mouse.get_pos()[0] >= self.x and pygame.mouse.get_pos()[0] <= self.x + self.width and \
       pygame.mouse.get_pos()[1] >= self.y and pygame.mouse.get_pos()[1] <= self.y + self.height:

        self.surfaceActive.blit(self.textSurfaceActive, (self.width / 2 - self.font.size(self.textActive)[0] / 2,
                                                   self.height / 2 - self.font.size(self.textActive)[1] / 2))

        self.surface.blit(self.surfaceActive, (self.x, self.y))

        if self.selected == False:
            if self.sounds != None:
                self.sounds[0].stop()
                self.sounds[1].stop()
                self.sounds[2].stop()
                self.sounds[0].play()
            self.selected = True

    else:

        self.surfaceInactive.blit(self.textSurfaceInactive, (self.width / 2 - self.font.size(self.textInactive)[0] / 2,
                                                     self.height / 2 - self.font.size(self.textInactive)[1] / 2))

        self.surface.blit(self.surfaceInactive, (self.x, self.y))

        if self.selected == True:
            if self.sounds != None:
                self.sounds[0].stop()
                self.sounds[1].stop()
                self.sounds[2].stop()
                self.sounds[1].play()
            self.selected = False

Code from the button class that checks if the button is clicked (this is inside the method .clickEvent which is called when the left mouse button is clicked):

    if self.command != None:

        if pygame.mouse.get_pos()[0] >= self.x and pygame.mouse.get_pos()[0] <= self.x + self.width and \
           pygame.mouse.get_pos()[1] >= self.y and pygame.mouse.get_pos()[1] <= self.y + self.height:    

            if self.sounds != None:
                self.sounds[2].play()
            self.command()

So my question is: Why is there a long delay and can I make it shorter?

标签: python pygame
7条回答
疯言疯语
2楼-- · 2020-02-10 07:37

I know this is old, but I found the best solution I have seen so far.

The fix is quite simple actually. I used to have delay in my pygame projects all the time because I would initialize pygame before initializing the mixer. (which always seemed the way you should do it to me).

However if you initialize the mixer before initializing pygame itself it gets rid of all delay. This fixed all my delay problems. hope it helps.

pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.mixer.init()
pygame.init()
查看更多
放荡不羁爱自由
3楼-- · 2020-02-10 07:38

Simply decreasing the size of the buffer, as often suggested for this problem, did not work for me. I found this solution. When initiating the mixer twice, the delay completely disappeared:

import pygame

pygame.mixer.pre_init(22050, -16, 2, 1024)
pygame.init()
pygame.mixer.quit()
pygame.mixer.init(22050, -16, 2, 1024)

It's a bit dirty and I don't know why it works, but hopefully it solves the problem for some people.

Tested on Ubuntu 16.04 LTS with Python 3.6 and pygame 1.9.4

查看更多
何必那么认真
4楼-- · 2020-02-10 07:47

In my situation the delay was between 0.2 and 0.5 sec. To call pygame.mixer.pre_init() is a very good solution but the delay also depends on the given values.

查看更多
啃猪蹄的小仙女
5楼-- · 2020-02-10 07:48

I had a sound delay, too. Now, this works fine for me:

pg.mixer.pre_init(44100, -16, 1, 512)
pg.init()
pg.mixer.init()

With pg.mixer.pre_init(22100, -16, 2, 64) the sound plays faster but is twisted, okay for sound effects but not for real music as background.

查看更多
爱情/是我丢掉的垃圾
6楼-- · 2020-02-10 07:51

Decreasing the size of the buffer will reduce the latency. The buffer must be a power of 2. The default buffer is 4096, but you can change it when you initialize mixer as shown below:

pygame.mixer.init(22100, -16, 2, 64)

More information can be found on the pygame docs

查看更多
Emotional °昔
7楼-- · 2020-02-10 07:51

I also had problems with sound lagging. I found that calling pygame.mixer.pre_init() before pygame.init() solved my problems:

pygame.mixer.pre_init(44100, -16, 1, 512)
pygame.init()
查看更多
登录 后发表回答