Change the pitch (and speed) of sound during playback in Python

I am working on a Python program that plays music. One of the functions will be a slider that the user can drag up or down to change the pitch when it is playing.

For example, if the pitch is set to 2, the sound will sound one octave higher, it will play twice as fast, and it will last one and a half times. All I really change is the playback speed, but I need to do this interactively in real time.

A good example of this functionality implemented in flash can be found here . (It takes a little to download, be patient.)

I looked through a lot of python audio files, but I did not find one that can change the pitch of the sound that is currently being played. I have several versions of Python, so there is no requirement for the version that the package supports. I am developing this on Windows 7.

Any suggestions?

+3
source share
4 answers

It sounds as if you want to reprogram the sound on the fly.

Perhaps you could try using the scikits.samplerate module . He uses the Secret Rabbit Code Library .

+1
source

Using Craig McQueen , I created a conceptual program.

wav mono "music.wav" ( , ) . . , - .

, , . , 2 . , . ( , ). , soundOutput.getLeft() < 0.2. , , , 0,2 . . , soundOutput.getLeft() . 0 .

, waveRead.readframes(100), , . .

import os, sys, wave, pygame, numpy, pymedia.audio.sound, scikits.samplerate

class Window:
    def __init__(self, width, height, minOctave, maxOctave):
        """
        width, height: the width and height of the screen.
        minOctave, maxOctave: the highest and lowest pitch changes. 0 is no change.
        """
        self.minOctave = minOctave
        self.maxOctave = maxOctave
        self.width = width
        self.mouseDown = False
        self.ratio = 1.0 # The resampling ratio
        waveRead = wave.open(os.path.join(sys.path[0], "music.wav"), 'rb')
        sampleRate = waveRead.getframerate()
        channels = waveRead.getnchannels()
        soundFormat = pymedia.audio.sound.AFMT_S16_LE
        soundOutput = pymedia.audio.sound.Output(sampleRate, channels, soundFormat)
        pygame.init()
        screen = pygame.display.set_mode((width, height), 0)
        screen.fill((255, 255, 255))
        pygame.display.flip()
        fout = open(os.path.join(sys.path[0], "musicdata.txt"), 'w') # For troubleshooting
        byteString = waveRead.readframes(1000) # Read at most 1000 samples from the file.
        while len(byteString) != 0:
            self.handleEvent(pygame.event.poll()) # This does not wait for an event.
            fout.write(str(soundOutput.getLeft()) + "\n") # For troubleshooting
            if soundOutput.getLeft() < 0.2: # If there is less than 0.2 seconds left in the sound buffer.
                array = numpy.fromstring(byteString, dtype=numpy.int16)
                byteString = scikits.samplerate.resample(array, self.ratio, "sinc_fastest").astype(numpy.int16).tostring()
                soundOutput.play(byteString)
                byteString = waveRead.readframes(500) # Read at most 500 samples from the file.
        waveRead.close()
        return

    def handleEvent(self, event):
        if event.type == pygame.QUIT or (event.type == pygame.KEYUP and event.key == pygame.K_ESCAPE):
            sys.exit()
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            self.mouseDown = True
            self.setRatio(event.pos)
        if event.type == pygame.MOUSEBUTTONUP and event.button == 1:
            self.mouseDown = False
        if event.type == pygame.MOUSEMOTION and self.mouseDown:
            self.setRatio(event.pos)
        return None

    def setRatio(self, point):
        self.ratio = 2 ** -(self.minOctave + point[0] * (self.maxOctave - self.minOctave) / float(self.width))
        print(self.ratio)

def main():
    Window(768, 100, -2.0, 2.0)

if __name__ == '__main__':
    main()

, , . Python 2.6.6, PyGame 1.9.1 python 2.6, NumPy 1.3.0 python 2.6, PyMedia 1.3.7.3 python 2.6 scikits.samplerate 0.3.1 python 2.6. , scikits.samplerate NumPy 1.4 , ( , ) setuptools

+3

, wxPython SetPlaybackRate(). wxWidget docs here.

SetPlaybackRate() , , , , , .

0

customization tools needed for scikits.samplerate 0.3.1

If you do not, you will continue to receive the ImportError error message: there is no module named pkg_resources

0
source

Source: https://habr.com/ru/post/1770613/


All Articles