반응형
fft_size가 frame_size( = 25) 이상인 가장 작은 2제곱 값
따라서 fft_size는 32
frame_shift = 10
# -*- coding: utf-8 -*-
import wave
import numpy as np
import matplotlib.pyplot as plt
if __name__ == "__main__":
wav_file = './data/wav/xxx.wav'
frame_size = 25
frame_shift = 10
out_plot = './spectrogram.png'
with wave.open(wav_file) as wav:
sample_frequency = wav.getframerate()
num_samples = wav.getnframes()
waveform = wav.readframes(num_samples)
waveform = np.frombuffer(waveform, dtype=np.int16)
frame_size = int(sample_frequency \
* frame_size * 0.001)
frame_shift = int(sample_frequency * frame_shift * 0.001)
fft_size = 1
while fft_size < frame_size:
fft_size *= 2
num_frames = (num_samples - frame_size) // frame_shift + 1
spectrogram = np.zeros((num_frames, int(fft_size/2)+1))
for frame_idx in range(num_frames):
start_index = frame_idx * frame_shift
frame = waveform[start_index : \
start_index + frame_size].copy()
frame = frame * np.hamming(frame_size)
spectrum = np.fft.fft(frame, n=fft_size)
absolute = np.abs(spectrum)
absolute = absolute[:int(fft_size/2) + 1]
log_absolute = np.log(absolute + 1E-7)
spectrogram[frame_idx, :] = log_absolute
plt.figure(figsize=(10,10))
plt.subplot(2, 1, 1)
time_axis = np.arange(num_samples) / sample_frequency
plt.plot(time_axis, waveform)
plt.title('waveform')
plt.xlabel('Time [sec]')
plt.ylabel('Value')
plt.xlim([0, num_samples / sample_frequency])
plt.subplot(2, 1, 2)
spectrogram -= np.max(spectrogram)
vmax = np.abs(np.min(spectrogram)) * 0.0
vmin = - np.abs(np.min(spectrogram)) * 0.7
plt.imshow(spectrogram.T[-1::-1,:],
extent=[0, num_samples / sample_frequency,
0, sample_frequency / 2],
cmap = 'gray',
vmax = vmax,
vmin = vmin,
aspect = 'auto')
plt.title('spectrogram')
plt.xlabel('Time [sec]')
plt.ylabel('Frequency [Hz]')
plt.savefig(out_plot)
컬러맵 종류
- 연속적인(Sequential) 컬러맵:
- 'viridis': 파이썬 데이터 시각화에서 가장 인기 있는 컬러맵
- 'plasma': 밝은 노란색부터 진한 자주색까지 색상 변화
- 'inferno': 어두운 보라에서 밝은 노란색으로 변화
- 'magma': 검은색에서 밝은 핑크/자주색으로 변화
- 발산형(Diverging) 컬러맵:
- 'coolwarm': 파란색에서 빨간색으로 변화
- 'RdBu': 빨간색-파란색 조합
- 'seismic': 지진학에서 많이 사용되는 컬러맵
FFT 이전에 프레임별로 해밍 윈도우 함수를 적용(windowing)하지 않는다고 가정(아래 코드 참조)
#frame = frame * np.hamming(frame_size)
FFT 시작과 끝부분의 불연속으로 인해 발생하는 노이즈 영향 때문에 흐리게 출력됨(아래 그림 참조)
반응형
'Python' 카테고리의 다른 글
Introducing Positron (data science) (0) | 2024.12.10 |
---|---|
Visualize FFT (0) | 2024.11.25 |
Visualize Speech Wave (0) | 2024.11.25 |
Python Task Scheduler (0) | 2024.11.20 |
[Python]파이썬 출력 화면 지우기 (0) | 2024.05.10 |
댓글