Построение временной последовательность в реальном времени

Всем привет. Нужна ваша срочная помощь. Как сделать так, чтобы график чертился в реальном времени. Те брал 1 значение из массива и заносил их на график, а потом брал следующую "точку". На данный момент он строит сразу все целиком. Заранее спасибо за помощь.

import numpy
import matplotlib.pyplot as plt
from scipy.io import wavfile
from scipy.fftpack import fft

#Указываем путь до аудио файла
myAudio = "C:\\Users\\denga\\Desktop\\gh\\22.wav"

#Чтение файла и получение частоты дискретизации и звукового объект
samplingFreq, mySound = wavfile.read(myAudio)

#Проверяем является ли wave-файл 16-битным или 32-битным. (24 бит не поддерживается)
mySoundDataType = mySound.dtype

#Мы можем преобразовать наш звуковой массив в значения с плавающей запятой в диапазоне от -1 до 1 следующим образом

mySound = mySound / (2.**15)

#Проверим точки отсчета и звуковой канал для двух каналов или для моноканала

mySoundShape = mySound.shape
samplePoints = float(mySound.shape[0])

#Получим продолжительность звукового файла
signalDuration = mySound.shape[0] / samplingFreq

#Если два канала, то выберем только один кана
mySoundOneChannel = mySound[:,0]

#Построение графика тона
#Мы можем представить звук, построив значения давления по оси времени.
#Создание массива выборочных точек в одном измерении
timeArray = numpy.arange(0, samplePoints, 1)

timeArray = timeArray / samplingFreq

# Масштабируем до миллисекунд
timeArray = timeArray * 1000

#Построим график тона
plt.plot(timeArray, mySoundOneChannel)
plt.xlabel('Время (ms)')
plt.ylabel('Амплитуда')
plt.show()


#График частотного содержания
#Мы можем получить частоту из амплитуды и времени с помощью БПФ, быстрого алгоритма преобразования Фурье
#Получим длину моего массива звуковых объектов
mySoundLength = len(mySound)

#Возьмем преобразование Фурье для данной точки отсчета
fftArray = fft(mySoundOneChannel)

numUniquePoints = int(numpy.ceil((mySoundLength + 1) / 2.0))
fftArray = fftArray[0:numUniquePoints]

#БПФ содержит как величину, так и фазу и задается комплексными числами в формате действительных + мнимых частей (a + ib).
#Принимая абсолютное значение, мы получаем только действительную часть.

fftArray = abs(fftArray)

#Масштабируйте массив fft по длине точек выборки, чтобы величина не зависела отдлина сигнала или его частота дискретизации

fftArray = fftArray / float(mySoundLength)

#БПФ имеет как положительную, так и отрицательную информацию. Площадь возводим в квадрат, чтобы получить только положительные значения
fftArray = fftArray **2

if mySoundLength % 2 > 0: #у нас есть нечетное число точек в FFT
         fftArray[1:len(fftArray)] = fftArray[1:len(fftArray)] * 2

else: #У нас есть чётное количество точек в БПФ
         fftArray[1:len(fftArray) -1] = fftArray[1:len(fftArray) -1] * 2

freqArray = numpy.arange(0, numUniquePoints, 1.0) * (samplingFreq / mySoundLength)

#Постройка спектра частоты
plt.plot(freqArray/1000, 10 * numpy.log10 (fftArray))
plt.xlabel('Частота (Khz)')
plt.ylabel('Мощность (dB)')
plt.show()

Ответы (1 шт):

Автор решения: mkkik

Вот пример, как можно отобразить процесс в "реальном времени" при помощи FuncAnimation:

import wave
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# https://file-examples-com.github.io/uploads/2017/11/file_example_WAV_1MG.wav
file = 'file_example_WAV_1MG.wav'

data = wave.open(file, 'r')

if data.getsampwidth() != np.int16().nbytes:
    raise TypeError("required 16-bit PCM")
nchannels = data.getnchannels()
nframes = data.getnframes()

fig, ax = plt.subplots(nchannels, 1)
samples = np.frombuffer(data.readframes(nframes), dtype=np.int16)

# выбран некоторый временной отрезок в 5000 отсчетов
samples = samples.reshape(-1, nchannels).T[:, 120000:125000]
samples_cnt = samples.shape[1]

xdata = []
ch1, ch2 = [ax.plot(xdata, [])[0] for ax in fig.axes]

def init():
    iinfo = np.iinfo(samples.dtype)
    plt.setp(ax, xlim=(0, samples_cnt), ylim=(iinfo.min, iinfo.max))
    return ch1, ch2

def update(i):
    xdata.append(i - 1)   
    ch1.set_data(xdata, samples[0, :i])
    ch2.set_data(xdata, samples[1, :i])
    return ch1, ch2

ani = FuncAnimation(fig, update, frames=range(1, samples_cnt), blit=True, 
                        init_func=init, interval=1, repeat=False)
plt.show()

P.S. Данный подход ограничен в производительности (низкий FPS), но может быть использован для демонстрационных задач.

→ Ссылка