Имитированные осциллограммы не должны отображать БПФ, подобные вашей фигуре, поэтому что-то очень неправильно, и, вероятно, не с БПФ, а с входной осциллограммой. Основная проблема в вашем сюжете - это не пульсации, а гармоники около 1000 Гц и субгармоника при 500 Гц. Имитированная форма волны не должна показывать ничего из этого (например, см. Мой график ниже).
Во-первых, вы, вероятно, захотите просто попытаться построить необработанный сигнал, и это, вероятно, укажет на очевидную проблему. Кроме того, кажется странным иметь волну, распакованную в шорты без знака, то есть "H", и особенно после этого, чтобы не иметь большой компонент с нулевой частотой.
Мне удалось получить довольно близкий дубликат к вашему БПФ, применив отсечение к сигналу, как было предложено как для субгармонических, так и для высших гармоник (и Тревора). Вы можете ввести обрезку либо в симуляции, либо в распаковке. В любом случае, я обошел это путем создания волновых форм в numpy для начала.
Вот как должно выглядеть правильное БПФ (т.е. в основном идеально, за исключением расширения пиков из-за окон)
Вот один из осциллограмм, которые были обрезаны (и очень похож на ваше БПФ, от субгармоники до точного паттерна трех высших гармоник около 1000 Гц)
Вот код, который я использовал для генерации этих
from numpy import *
from pylab import ion, plot, draw, show, xlabel, ylabel, figure
sample_rate = 20000.
times = arange(0, 10., 1./sample_rate)
wfm0 = sin(2*pi*200.*times)
wfm1 = sin(2*pi*500.*times) *(10.-times)/10.
wfm = wfm0+wfm1
# int test
#wfm *= 2**8
#wfm = wfm.astype(int16)
#wfm = wfm.astype(float)
# abs test
#wfm = abs(wfm)
# clip test
#wfm = clip(wfm, -1.2, 1.2)
fft_length = 5*2048.
total_num_samps = len(times)
num_fft = (total_num_samps / fft_length ) - 2
temp = zeros((num_fft,fft_length), float)
for i in range(num_fft):
temp[i,:] = wfm[i*fft_length:(i+1)*fft_length]
pts = fft_length/2+1
data = (abs(fft.rfft(temp, fft_length)) / (pts))[:pts]
x_axis = arange(pts)*sample_rate*.5/pts
spec_range = pts
plot(x_axis, data[2], linewidth=3)
xlabel("freq (Hz)")
ylabel('abs(FFT)')
show()