Fade Between Two Music Tracks in-progress in Pygame

前端 未结 4 1047
南方客
南方客 2020-12-31 11:50

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,

4条回答
  •  遥遥无期
    2020-12-31 12:20

    So it looks like what you want to do in pygame is create two 'Sound' objects, and create a linear interpolation on the volume between the two of them.

    I would create two vectors, each from [0,100], and relate them inversely with some constant. So when sound A is at 100, sound b is at 0. Then when an action occurs, you modify the constant.

    t=0
    A: [0 ... 100]
    B: [0 ... 100]

    t=1
    ACTION

    t=1.1
    A:[0 .. 50 .. 100]
    B:[0 .. 50 .. 100]

    t=2
    A:[0 ... 100]
    B:[0 ... 100]

    Now some code. I'm not familiar with pygame, but this should put you on the right track.

    class Song(object):
        def __init__(self, songfilename):
            self.song = pygame.mixer.Sound(songfilename)
    
        def setVolume(self, somenumber):
            #number validation
            #possibly do some volume curve here if you wanted
            self.song.set_volume(somenumber)
    
    class SongFader(object):
        def __init__(self, song1, song2):
            self.song1 = song1
            self.song2 = song2
            self.__xAxisMax = 100
            self.__xAxisMin = 0
    
        def fade(self, xaxis):
            assert(self.__xAxisMin <= xaxis <= self.__xAxisMax) 
              #could be any numbers you want. 
              #i chose 0-100 for convenience
            self.song1.setVolume(xaxis)
            self.song2.setVolume(self.__xAxisMax-xaxis)
    
    song1 = Song('Song1.wav')
    song2 = Song('Song2.wav')
    fader = SongFader(song1, song2)
    
    #Inside some event loop when you action is triggered
    fader.fade(100) #Only song2 is playing
    fader.fade(50)  #Songs are evenly split
    fader.fade(0)   #Only left song is playing
    

    edit

    The linear interpolation is probably the more important concept here, so i have modified the fader class, with inspiration from Eric 's thread idea.

    class SongFader(object):
        def __init__(self, song1, song2):
            self.song1 = song1
            self.song2 = song2
            self.lefttoright = False
            self.starttime = 0
            self.endtime = 0
    
    
        def fade(self, starttime, fadeleft):
            self.lefttoright = fadeleft == True #Being verbose here
            self.starttime = starttime #assuming time is in millis
            self.endtime = starttime + 1000
            Thread(target = self.fadeHelper).start()
    
        #this is where you define how the two songs are faded
        def fadeHelper(self):
            #if using thread, make sure you mutex the 'self.' variables
            starttime = self.starttime
            endtime = self.endtime
            lefttoright = self.lefttoright
            while starttime < endtime:
                fadevalue = (starttime - endtime) / 1000 #a val between [0,1]
                if lefttoright:
                    self.song1.setVolume(fadevalue)
                    self.song2.setVolume(1-fadevalue)
                else:
                    self.song1.setVolume(1-fadevalue)
                    self.song2.setVolume(fadefalue)
                starttime = getGameTimeFromSomewhere()
    

提交回复
热议问题