본문 바로가기
Python

Visualize FFT

by YJHTPII 2024. 11. 25.
반응형

복소수 스펙트럼 계산:

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

댓글