Python change pitch of wav file [closed]

孤街醉人 提交于 2020-05-25 04:17:39

问题


I need any python library to change pitch of my wav file without any raw audio data processing. I spent couple hours to find it, but only found some strange raw data processing code snippets and video, that shows real-time pitch shift, but without source code.


回答1:


Since a wav file basically is raw audio data, you won't be able to change the pitch without "raw audio processing".

Here is what you could do. You will need the wave (standard library) and numpy modules.

import wave
import numpy as np

Open the files.

wr = wave.open('input.wav', 'r')
# Set the parameters for the output file.
par = list(wr.getparams())
par[3] = 0  # The number of samples will be set by writeframes.
par = tuple(par)
ww = wave.open('pitch1.wav', 'w')
ww.setparams(par)

The sound should be processed in small fractions of a second. This cuts down on reverb. Try setting fr to 1; you'll hear annoying echos.

fr = 20
sz = wr.getframerate()//fr  # Read and process 1/fr second at a time.
# A larger number for fr means less reverb.
c = int(wr.getnframes()/sz)  # count of the whole file
shift = 100//fr  # shifting 100 Hz
for num in range(c):

Read the data, split it in left and right channel (assuming a stereo WAV file).

    da = np.fromstring(wr.readframes(sz), dtype=np.int16)
    left, right = da[0::2], da[1::2]  # left and right channel

Extract the frequencies using the Fast Fourier Transform built into numpy.

    lf, rf = np.fft.rfft(left), np.fft.rfft(right)

Roll the array to increase the pitch.

    lf, rf = np.roll(lf, shift), np.roll(rf, shift)

The highest frequencies roll over to the lowest ones. That's not what we want, so zero them.

    lf[0:shift], rf[0:shift] = 0, 0

Now use the inverse Fourier transform to convert the signal back into amplitude.

    nl, nr = np.fft.irfft(lf), np.fft.irfft(rf)

Combine the two channels.

    ns = np.column_stack((nl, nr)).ravel().astype(np.int16)

Write the output data.

    ww.writeframes(ns.tostring())

Close the files when all frames are processed.

wr.close()
ww.close()



回答2:


You can try pydub for quick and easy pitch change across entire audio file and for different formats (wav, mp3 etc).

Here is a working code. Inspiration from here and refer here for more details on pitch change.

from pydub import AudioSegment
from pydub.playback import play

sound = AudioSegment.from_file('in.wav', format="wav")

# shift the pitch up by half an octave (speed will increase proportionally)
octaves = 0.5

new_sample_rate = int(sound.frame_rate * (2.0 ** octaves))

# keep the same samples but tell the computer they ought to be played at the 
# new, higher sample rate. This file sounds like a chipmunk but has a weird sample rate.
hipitch_sound = sound._spawn(sound.raw_data, overrides={'frame_rate': new_sample_rate})

# now we just convert it to a common sample rate (44.1k - standard audio CD) to 
# make sure it works in regular audio players. Other than potentially losing audio quality (if
# you set it too low - 44.1k is plenty) this should now noticeable change how the audio sounds.
hipitch_sound = hipitch_sound.set_frame_rate(44100)

#Play pitch changed sound
play(hipitch_sound)

#export / save pitch changed sound
hipitch_sound.export("out.wav", format="wav")



回答3:


I recommend trying Librosa's pitch shift function: https://librosa.github.io/librosa/generated/librosa.effects.pitch_shift.html

import librosa
y, sr = librosa.load('your_file.wav', sr=16000) # y is a numpy array of the wav file, sr = sample rate
y_shifted = librosa.effects.pitch_shift(y, sr, n_steps=4) # shifted by 4 half steps


来源:https://stackoverflow.com/questions/43963982/python-change-pitch-of-wav-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!