#python #plot #signal-processing #fft #frequency
#питон #сюжет #обработка сигналов #бпф #частота
Вопрос:
Я столкнулся с очень странной проблемой с моими сюжетами. Мой код записывает мой голос с микрофона, а затем составляет несколько графиков. График голоса во временной области, график в частотной области и спектрограмма. Проблема в том, что мой график в частотной области не соответствует действительности. Например, взгляните на мои сюжеты.
Поэтому в этой записи я говорю «раз, два, три, четыре» или что-то в этом роде. График временной области действительно имеет смысл. Спектрограмма также в моих глазах имеет смысл, потому что самые громкие значения Фурье находятся на нормальных частотах человеческого голоса ~100 Гц.
Проблема в том, что
Мое короткое преобразование Фурье в частотной области, похоже, отображает очень высокие частоты с очень большой величиной, а частоты человеческого голоса 1-1000 имеют нулевое значение.
Так что же, может быть, происходит не так? Ниже я даю свой код
import matplotlib.pyplot as plt import numpy as np import scipy.fft import sounddevice as sd from scipy import signal, fft Fs = 8000 # Sampling frequency duration = 5 # Recording duration in seconds voice = sd.rec(frames=duration * Fs, samplerate=Fs, channels=1, dtype='int16') # Capture the voice # frames indicate indirectly the duration of record, dtype is 16 bits per sample. sd.wait() # close after recording finish time = np.linspace(0, len(voice - 1) / Fs, len(voice - 1)) # split x axis in voice-1 points # points have 1/Fs distance each other plt.plot(voice / len(voice)) plt.ylabel('Voice amplitude') plt.xlabel('No of sample') plt.title("Voice Signal with respect to sample number") plt.show() plt.plot(time, voice / len(voice)) # plot in seconds plt.title("Voice Signal") plt.xlabel("Time [seconds]") plt.ylabel("Voice amplitude") plt.show() plt.plot((10**3)*time, voice / len(voice)) # plot in milliseconds plt.title("Voice Signal") plt.xlabel("Time [milliseconds]") plt.ylabel("Voice amplitude") plt.show() N = len(voice) # Fourier transform F = scipy.fft.fft(voice) / N #f = np.linspace(0, Fs - Fs / N, N) f = fft.fftfreq(n=N, d=1 / Fs)[:N // 2] #f = np.linspace(0, 4000, N//2) plt.plot(f, abs(F[0:N // 2])) plt.title("FFT of the signal") plt.xlabel('Frequency') plt.ylabel('Power of Frequency') plt.show() Voice = voice.flatten() # formatting Voice 2-D array to numpy 1-D array print(Voice) freq, t, stft = signal.spectrogram(Voice, Fs, mode='complex') #Sxx, freq, t = plt.specgram(Voice, Fs=Fs, mode='magnitude') print(stft) print(freq) print(t) plt.pcolormesh(t, freq, abs(stft), shading='gouraud') plt.title('Spectrogramm using STFT amplitude') plt.ylabel('Frequency [Hz]') plt.xlabel('Time [seconds]') plt.show()
Комментарии:
1. Попробуйте построить данные stft в децибелах
stft_db = 20*np.log10(abs(stft))
и построить их с помощью команды pcolormesh. Тогда высшие гармоники будет легче увидеть. Ваш график спектрограммы действительно кажется разумным для голосовых данных, учитывая линейный масштаб.2. … и добавьте цветовую панель для приятного прикосновения:
plt.colorbar()
3. Ваш совет касается спектрограммы? В этом нет никакой проблемы. Проблема заключается в графике частоты stft (второй график). Вы можете видеть на втором графике высокие значения для слишком высоких частот, но мои голосовые частоты имеют нулевое значение
4. Да, согласен, второй сюжет выглядит шатким
5. Проверьте ответ от @SleuthEye , я думаю, что это хорошая зацепка
Ответ №1:
С помощью 2D — массива voice
(скорее всего, Nx1, для монофонической записи) scipy.fft.fft
в конечном итоге вычисляется партия из N 1D БПФ длиной 1. Поскольку БПФ последовательности из 1 значения является идентичностью, то, что вы видите на своем 2-м графике, является абсолютным значением первой половины вашего сигнала во временной области.
Попробуйте вычислить БПФ на 1D массиве (один канал), например, с помощью :
F = scipy.fft.fft(voice[:,0]) / N
Комментарии:
1. И позже он делает
Voice = voice.flatten()
это для stft, что также неправильно2. Абсолютно идеально. Большое спасибо!. Я вообще новичок в python, чрезвычайно новый в цифровой обработке сигналов с помощью python. Я знал основные принципы сигналов и систем, но на самом деле эта проблема связана с некоторыми «странностями python». Также я отметил, что вы также заметили, что мой второй график был таким же, как и первый, с сокращением отрицательных значений.
3. @dankal я сгладил массив, потому что у меня была ошибка с размерами внутри signal.spectogram и pcoloromesh, поэтому мне пришлось это сделать, но знайте, что я сгладил массив перед fft.fft(голос), и все функции работают с начальным сглаживанием
4. @Panos Хорошо, просто помните, что если вы будете анализировать стереозапись, у вас будет 2 канала — образцы Nx2 — и выравнивание будет неправильным.
5. Да, я думаю, что понимаю, в чем дело. Если бы у меня была стереосистема, у меня был бы большой массив со множеством 2-элементных массивов. В этом случае, на самом деле, я не могу себе представить, как будут работать моя спектрограмма и pcolormesh и если возникнет ошибка, но хорошо, когда придет время, я попытаюсь с этим справиться