Search code examples
pythonpygameplayback

Fade Between Two Music Tracks in-progress in Pygame


My intention is to have two music tracks, which are similar in nature, fade between each other at various times. When such a fade occurs, one music track should fade from full volume to muted in a short period of time, and, simultaneously, the other track should fade from 0 to 100 and continue playing from the same time index. They must be able to do this dynamically at any time - when a certain action occurs, the fade will occur and the new track will start playing at the same position that the other one left off at.

This might be plausible by either using volume manipulation or by starting and stopping the music (however, it appears that only a "fadeout" option exists, and there is a lack of a "fadein" option). How can I do this? What is the best method, if any, that exists? If it is impossible using Pygame, alternatives to Pygame are acceptable.


Solution

  • Try this, it's pretty straight forward..

    import pygame
    
    pygame.mixer.init()
    pygame.init()
    
    # Maybe you can subclass the pygame.mixer.Sound and
    # add the methods below to it..
    class Fader(object):
        instances = []
        def __init__(self, fname):
            super(Fader, self).__init__()
            assert isinstance(fname, basestring)
            self.sound = pygame.mixer.Sound(fname)
            self.increment = 0.01 # tweak for speed of effect!!
            self.next_vol = 1 # fade to 100 on start
            Fader.instances.append(self)
    
        def fade_to(self, new_vol):
            # you could change the increment here based on something..
            self.next_vol = new_vol
    
        @classmethod
        def update(cls):
            for inst in cls.instances:
                curr_volume = inst.sound.get_volume()
                # print inst, curr_volume, inst.next_vol
                if inst.next_vol > curr_volume:
                    inst.sound.set_volume(curr_volume + inst.increment)
                elif inst.next_vol < curr_volume:
                    inst.sound.set_volume(curr_volume - inst.increment)
    
    sound1 = Fader("1.wav")
    sound2 = Fader("2.wav")
    sound1.sound.play()
    sound2.sound.play()
    sound2.sound.set_volume(0)
    
    # fading..
    sound1.fade_to(0)
    sound2.fade_to(1)
    
    
    while True:
        Fader.update() # a call that will update all the faders..