Python改变wav文件的音高[关闭]

Posted

技术标签:

【中文标题】Python改变wav文件的音高[关闭]【英文标题】:Python change pitch of wav file [closed] 【发布时间】:2017-10-13 07:45:16 【问题描述】:

我需要任何 python 库来更改我的 wav 文件的音高,而无需任何原始音频数据处理。 我花了几个小时才找到它,但只找到了一些奇怪的原始数据处理代码 sn-ps 和视频,显示实时音高变化,但没有源代码。

【问题讨论】:

网站规则声明我们不是在这里为您寻找图书馆或为此创建图书馆。如果您已经搜索但找不到 - 很可能没有,您必须自己编写。至少这是常态,我只是通知您,以防您没有得到任何答案或您的问题被关闭。 在您的搜索引擎中输入ffmpeg python,然后从那里获取。 【参考方案1】:

由于wav 文件基本上原始音频数据,如果没有“原始音频处理”,您将无法更改音高

这是你可以做的。 您将需要 wave(标准库)和 numpy 模块。

import wave
import numpy as np

打开文件。

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)

声音应该在几分之一秒内处理完毕。这减少了混响。尝试将fr 设置为 1;你会听到烦人的回声。

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):

读取数据,将其拆分为左右声道(假设为立体声 WAV 文件)。

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

使用 numpy 内置的快速傅里叶变换提取频率。

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

滚动阵列以增加音高。

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

最高频率滚动到最低频率。这不是我们想要的,所以将它们归零。

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

现在使用傅里叶逆变换将信号转换回幅度。

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

结合两个渠道。

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

写入输出数据。

    ww.writeframes(ns.tostring())

处理完所有帧后关闭文件。

wr.close()
ww.close()

【讨论】:

好的。我可以读取第一秒并将音高更改 500(什么?),例如,我想将音高更改 1 个半音。我如何读取整个文件并为 whle 文件更改一次音高。我不敢相信只改变每秒的音高就可以了。当我尝试readframes(wr.getnframes())np.roll(lf, 500) 时,音高不会改变,我需要使用另一个更大的值而不是 500。 @DanielReshetnikov 我已经重写了我的答案。事实证明,您需要一次处理几分之一秒才能防止讨厌的回声。 现在我可以转置整个文件了。它好一点。现在我可以以赫兹为单位更改音高,但不幸的是,无法将赫兹转换为半音(我的错 - 我没有在这个问题中概述它)。 如果想稍微移动一下怎么办,比如 3.4 hz 当我从这个答案运行代码时,我得到了这个问题: ``ValueError Traceback (most recent call last) in 5 6 # Extract the使用 numpy 内置的快速傅里叶变换的频率。 ----> 7 lf, rf = np.fft.rfft(left), np.fft.rfft(right) 8 9 # 滚动数组以增加音高。 <__array_function__ internals> in rfft(*args, **kwargs) [...] ValueError:指定的 FFT 数据点数 (0) 无效。 ``【参考方案2】:

您可以尝试pydub 快速轻松地更改整个音频文件和不同格式(wav、mp3 等)的音高。

这是一个工作代码。来自here 的灵感,请参阅here 了解有关音高变化的更多详细信息。

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")

【讨论】:

我试过你的代码。音高变化很好,但播放速度也在变化。我只需要改变音高。 有点远射,但有没有办法用这种方法保持速度? 你的两个 URL 都重定向到 github 上的同一个问题【参考方案3】:

我建议尝试 Librosa 的音高转换功能: 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

【讨论】:

音质好,速度快。

以上是关于Python改变wav文件的音高[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 python 脚本停止/关闭音频文件(mp3/.wav)

采样率改变正弦波的音高,sound() 函数,MATLAB

在将数据输入 FFT 用于音频频谱分析仪之前,使用 python 将 wav 文件转换为 csv 文件 [关闭]

如何使用 java 从 pcm 字节数组 .wav 文件中获取频率和音高?

如何在不使用 Aubio 的情况下获得 .wav 文件的平均音高?

使用 DirectSound 进行音高转换