반응형
복소수 스펙트럼 계산:
spectrum: np.fft.fft(frame)
frame은 0.58초에서 시작 1024(2의 제곱승)만큼 크기
진폭스펙트럼 : 복소수 스펙터럼의 절대치 np.abs(spectrum)
좌우대칭이므로 좌측만 사용 0~512까지 절대치 취함
로그 진폭 스펙트럼: 흔들리는 폭이 크므로 로그를 취함 np.log
flooring: 진폭이 0인 주파수가 있으면 로그를 취할 때 마이너스 무한대 가능
아주 작은 수인 1E-7(10의 마이너스 7승)을 더함
# -*- coding: utf-8 -*-
import wave
import numpy as np
import matplotlib.pyplot as plt
if __name__ == "__main__":
wav_file = './data/wav/fft.wav'
target_time = 0.58
fft_size = 1024
out_plot = './spectrum/spectrum.png'
with wave.open(wav_file) as wav:
sampling_frequency = wav.getframerate()
# 샘플링 주파수 출력
print(f'Sampling Frequency: {sampling_frequency} Hz')
waveform = wav.readframes(wav.getnframes())
waveform = np.frombuffer(waveform, dtype=np.int16)
target_index = np.int(target_time * sampling_frequency)
frame = waveform[target_index: target_index + fft_size]
spectrum = np.fft.fft(frame)
absolute = np.abs(spectrum)
absolute = absolute[:np.int(fft_size/2) + 1]
#log_absolute = np.log(absolute + 1E-7)
threshold = 1E-5
log_func = lambda x: np.log(x + 1E-7) if x < threshold else np.log(x)
log_absolute = np.vectorize(log_func)(absolute)
plt.figure(figsize=(10,10))
plt.subplot(2, 1, 1)
time_axis = target_time \
+ np.arange(fft_size) / sampling_frequency
plt.plot(time_axis, frame)
plt.title('waveform')
plt.xlabel('Time [sec]')
plt.ylabel('Value')
plt.xlim([target_time,
target_time + fft_size / sampling_frequency])
plt.subplot(2, 1, 2)
freq_axis = np.arange(np.int(fft_size/2)+1) \
* sampling_frequency / fft_size
plt.plot(freq_axis, log_absolute)
plt.title('log-absolute spectrum')
plt.xlabel('Frequency [Hz]')
plt.ylabel('Value')
plt.xlim([0, sampling_frequency / 2])
plt.savefig(out_plot)
코드수정: absolute가 0에 가까운 값일 때만 선별적으로 플로어링 처리하는 방법
선별적으로 플로어링 처리를 하기 위해서는 다음과 같은 방법들을 고려할 수 있습니다:
1. 조건부 로그 변환 방식:
threshold = 1E-5
log_absolute = np.where(absolute < threshold,
np.log(absolute + 1E-7),
np.log(absolute))
2. 마스킹을 이용한 방식:
threshold = 1E-5
mask = absolute < threshold
log_absolute = np.log(np.where(mask, absolute + 1E-7, absolute))
3.람다 함수를 활용한 방식:
threshold = 1E-5
log_func = lambda x: np.log(x + 1E-7) if x < threshold else np.log(x)
log_absolute = np.vectorize(log_func)(absolute)
각 방법의 특징:
- threshold: 작은 값으로 취급할 기준값 (예: 1E-5, 1E-4 등)
- 조건부로 아주 작은 값에만 작은 값(1E-7)을 더해 로그 변환
- 다른 일반적인 값들은 그대로 로그 변환
반응형
'Python' 카테고리의 다른 글
Introducing Positron (data science) (0) | 2024.12.10 |
---|---|
Visualize STFT (0) | 2024.11.27 |
Visualize Speech Wave (0) | 2024.11.25 |
Python Task Scheduler (0) | 2024.11.20 |
[Python]파이썬 출력 화면 지우기 (0) | 2024.05.10 |
댓글