简体   繁体   English

Python:改变音频文件的音高

[英]Python: Change Pitch of Audio File

this is my first post on stack. 这是我在堆栈上的第一篇文章。 So far this site has been very helpful, but I am a novice and need a clear explanation to my problem, which is related to pitch-shifting audio in Python. 到目前为止,这个网站非常有用,但我是一个新手,需要清楚解释我的问题,这与Python中的音调转换音频有关。 I have the current modules installed: numpy, scipy, pygame, and the scikits "samplerate" api. 我安装了当前的模块:numpy,scipy,pygame和scikits“samplerate”api。

My goal is to take a stereo file and play it back at a different pitch in as few steps as possible. 我的目标是采用立体声文件,并以尽可能少的步骤以不同的音高播放。 Currently, I load the file into an array using pygame.sndarray, then apply a samplerate conversion using scikits.samplerate.resample, then convert the output back to a sound object for playback using pygame. 目前,我使用pygame.sndarray将文件加载到数组中,然后使用scikits.samplerate.resample应用samplerate转换,然后将输出转换回声音对象以使用pygame进行回放。 The problem is garbage audio comes out of my speakers. 问题是垃圾音频来自我的扬声器。 Surely I'm missing a few steps (in addition to not knowing anything about math and audio). 当然,我错过了几个步骤(除了对数学和音频一无所知)。

Thanks. 谢谢。

import time, numpy, pygame.mixer, pygame.sndarray
from scikits.samplerate import resample

pygame.mixer.init(44100,-16,2,4096)

# choose a file and make a sound object
sound_file = "tone.wav"
sound = pygame.mixer.Sound(sound_file)

# load the sound into an array
snd_array = pygame.sndarray.array(sound)

# resample. args: (target array, ratio, mode), outputs ratio * target array.
# this outputs a bunch of garbage and I don't know why.
snd_resample = resample(snd_array, 1.5, "sinc_fastest")

# take the resampled array, make it an object and stop playing after 2 seconds.
snd_out = pygame.sndarray.make_sound(snd_resample)
snd_out.play()
time.sleep(2)

Your problem is that pygame works with numpy.int16 arrays but the call to resample return a numpy.float32 array: 你的问题是,pygame的工作与numpy.int16阵列但将呼叫resample返回numpy.float32阵列:

>>> snd_array.dtype
dtype('int16')
>>> snd_resample.dtype
dtype('float32')

You can convert resample result to numpy.int16 using astype : 您可以将resample结果numpy.int16使用astype

>>> snd_resample = resample(snd_array, 1.5, "sinc_fastest").astype(snd_array.dtype)

With this modification, your python script plays the tone.wav file nicely, at a lower pitch and a lower speed. 通过这个修改,你的python脚本很好地播放tone.wav文件,以较低的音高和较低的速度播放。

Your best bet is probably using python audiere. 你最好的选择可能是使用python audiere。

Here is a link, I used it to do the same sort of thing, it's very easy, just read all the documentation. 这是一个链接,我用它来做同样的事情,它很简单,只需阅读所有文档。

http://audiere.sourceforge.net/home.php http://audiere.sourceforge.net/home.php

Most likely the scikits.samplerate.resample is "thinking" your audio is in another format than 16bit stereo. 很可能scikits.samplerate.resample“思考”你的音频是另一种格式而不是16位立体声。 Check the documentation on scikits.samplerate on where to select the proper audio format in your array - If it resampled 16 bit audio treating it as 8 bit garbage is what would come out. 检查scikits.samplerate上关于在阵列中选择正确音频格式的位置的文档 - 如果重新采样16位音频,将其视为8位垃圾就会出现。

From the scikits.samplerate.resample documentation: scikits.samplerate.resample文档:

If input has rank 1, than all data are used, and are assumed to be from a mono signal. 如果输入具有等级1,则使用所有数据,并且假设它们来自单声道信号。 If rank is 2, the number columns will be assumed to be the number of channels. 如果rank为2,则数字列将被假定为通道数。

So I think what you need to do is something like this to pass the stereo data to resample in the format it expects: 所以我认为你需要做的是将立体声数据传递给它所期望的格式resample

snd_array = snd_array.reshape((-1,2))

snd_resample = resample(snd_array, 1.5, "sinc_fastest")

snd_resample = snd_resample.reshape(-1) # Flatten it out again

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM