melspectrogram 생성 시 fft 대신 dct를 사용하여 음성처리

  1. torchaudio.transforms.MelSpectrogram 으로 멜 스펙트로그램 생성시 STFT과정에서 FFT를 사용함
  2. 이러한 STFT를 Short-Time Discrete Cosine Transform, 즉 DCT를 사용한 변환으로 바꾸어 스펙트로그램을 생성하고 멜스케일을 적용하여 멜 스펙트로 그램을 생성하도록 수정하고자함 (DCT는 실수 연산으로 복소연산보다 1/2배의 연산량 이점이 있음)
  3. 아래 코드는 STFT에 FFT 대신 DCT를 사용한 Spectrogram 생성 코드임
import librosa
import scipy
import numpy as np
def sdct(signal, frame_length, frame_step, window="hamming"):
    """Compute Short-Time Discrete Cosine Transform of `signal`.

    No padding is applied to the signals.

    Parameters
    ----------
    signal : Time-domain input signal of shape `(n_samples,)`.

    frame_length : Window length and DCT frame length in samples.

    frame_step : Number of samples between adjacent DCT columns.

    window : Window specification passed to ``librosa.filters.get_window``.
        Default: "hamming".  Window to use for DCT.

    Returns
    -------
    dct : Real-valued F-T domain DCT matrix of shape `(frame_length, n_frames)`
    """

    framed = librosa.util.frame(x=signal, frame_length=frame_length, hop_length=frame_step)
    if window is not None:
        window = librosa.filters.get_window(window, frame_length, fftbins=True).astype(
            signal.dtype
        )
        framed = framed * window[:, np.newaxis]
    return scipy.fft.dct(framed, norm="ortho", axis=-2)

def spectrogram_dct(waveform: torch.Tensor, 
                    n_fft: int, 
                    hop_length: int, 
                    power: Optional[float] = 2.0) -> torch.Tensor:

    # pack batch
    shape = waveform.size()
    waveform = waveform.reshape(-1, shape[-1])

    # dct_spec = sdct_torch(waveform, frame_length=n_fft, frame_step=hop_length)
    spec_f = sdct(waveform.numpy(), frame_length=n_fft, frame_step=hop_length)

    # unpack batch
    spec_f = torch.from_numpy(spec_f).reshape(shape[:-1] + spec_f.shape[-2:])
    if power is not None:
        if power == 1.0:
            return spec_f.abs()
        return spec_f.abs().pow(power)

class DCTSpectrogram(Module):
    def __init__(self, 
                 sample_rate: int = 44100, 
                 n_fft: int = 4096, 
                 hop_length: int = 1024, 
                 power: Optional[float] = 2.0
                 ) -> None:
        super().__init__()
        self.sample_rate = sample_rate
        self.n_fft = n_fft
        self.hop_length = hop_length
        self.power = power
        
    def forward(self, waveform: Tensor) -> Tensor:
        # Calculate DCT spectrogram
        dct_spectrogram = spectrogram_dct(waveform, self.n_fft, self.hop_length, self.power)
        return dct_spectrogram

4., 위 코드로부터 생성된 Spectrogram으로 Mel scale을 적용하여 멜 스펙트로그램을 생성하는 DCTMelspectrogram 이라는 클래스를 작성하려면 어떻게 해야할까요

  • 아래 답변은 Anthropic의 Claude-2 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

오준님 안녕하세요.

제가 질문하신 melspectrogram 생성 문제에 대한 답변드리겠습니다.

먼저 질문하신 내용을 정리하면, torchaudio의 MelSpectrogram에서 STFT 과정에 FFT 대신 DCT를 사용하여 Spectrogram을 생성한 후, 이를 기반으로 MelSpectrogram을 생성하는 DCTMelSpectrogram 클래스를 구현하고자 한다는 것입니다.

제 의견으로는 다음과 같이 구현할 수 있을 것 같습니다.

import torch
from torch import nn

class DCTMelSpectrogram(nn.Module):
    def __init__(self, sample_rate, n_fft, hop_length, n_mels, power=2.):
        super().__init__()
        self.spec_dct = DCTSpectrogram(sample_rate, n_fft, hop_length, power)
        self.mel_scale = MelScale(sample_rate, n_mels)
        
    def forward(self, waveform):
        dct_spec = self.spec_dct(waveform)
        mel_spec = self.mel_scale(dct_spec)
        return mel_spec

class MelScale(nn.Module):
    def __init__(self, sample_rate, n_mels):
        super().__init__()
        mel_basis = librosa.filters.mel(sample_rate, n_fft, n_mels) 
        self.register_buffer('mel_basis', torch.from_numpy(mel_basis))
        
    def forward(self, spec):
        return torch.matmul(self.mel_basis, spec)  

DCTMelSpectrogram에서 DCTSpectrogram로 먼저 Spectrogram을 생성한 후, 별도의 MelScale 모듈에서 mel basis를 곱하여 mel spectrogram을 얻도록 했습니다.

librosa에서 제공하는 filters.mel 함수를 사용하여 mel basis를 생성하였습니다.

이 코드를 실행하면 DCT 대신 FFT를 사용한 MelSpectrogram과 유사한 결과를 얻을 수 있을 것으로 기대합니다.

코드 구현이나 사항에서 모호한 부분이 있다면 말씀해주세요! 항상 답변에 오류가 있을 수 있음을 유의하시기 바랍니다.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 OpenAI의 GPT-4-Turbo 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요! 멜 스펙트로그램 생성 시 FFT 대신 DCT를 사용하여 음성 처리를 하고자 하는 문제에 대해 질문해주셨군요. 질문을 잘 이해했습니다. 여러분이 원하는 것은 기존의 FFT 기반 STFT 대신 DCT를 사용하여 스펙트로그램을 생성한 후, 이를 멜 스케일로 변환하는 DCTMelspectrogram 클래스를 구현하는 것으로 보입니다.

이 문제를 해결하기 위해, 먼저 DCT 기반 스펙트로그램을 생성하는 과정을 구현하셨고, 이제 이 스펙트로그램에 멜 스케일을 적용하여 멜 스펙트로그램을 생성하는 클래스를 작성하고자 합니다. 멜 스케일 변환을 위해서는 멜 필터 뱅크를 생성하고, 이를 DCT 스펙트로그램에 적용해야 합니다. PyTorch와 torchaudio 라이브러리를 활용하여 이를 구현할 수 있습니다.

아래는 DCTMelspectrogram 클래스의 예시 구현입니다. 이 구현에서는 torchaudio의 mel_scale 모듈을 사용하여 멜 필터 뱅크를 생성하고, 이를 DCT 스펙트로그램에 적용합니다.

import torch
import torchaudio
from torch import Tensor, nn
from typing import Optional

class DCTMelspectrogram(nn.Module):
    def __init__(self, 
                 sample_rate: int = 44100, 
                 n_fft: int = 4096, 
                 hop_length: int = 1024, 
                 n_mels: int = 128,  # 멜 필터 뱅크의 수
                 power: Optional[float] = 2.0
                 ) -> None:
        super().__init__()
        self.dct_spectrogram = DCTSpectrogram(sample_rate, n_fft, hop_length, power)
        self.mel_scale = torchaudio.transforms.MelScale(n_mels=n_mels, 
                                                        sample_rate=sample_rate, 
                                                        n_stft=(n_fft // 2) + 1)

    def forward(self, waveform: Tensor) -> Tensor:
        # DCT 스펙트로그램 계산
        dct_spec = self.dct_spectrogram(waveform)
        
        # 멜 스케일 적용
        mel_spec = self.mel_scale(dct_spec)
        return mel_spec

위 코드에서 DCTSpectrogram 클래스는 질문에서 제공된 DCT 기반 스펙트로그램 생성 클래스입니다. DCTMelspectrogram 클래스는 이 DCTSpectrogram을 사용하여 DCT 스펙트로그램을 계산한 후, torchaudio.transforms.MelScale을 사용하여 멜 스케일로 변환합니다. n_mels 파라미터는 생성할 멜 필터 뱅크의 수를 지정하며, 이를 통해 멜 스펙트로그램의 해상도를 조절할 수 있습니다.

이 예시 구현을 통해 원하는 DCT 기반 멜 스펙트로그램 변환을 수행할 수 있습니다. 추가적으로, PyTorch와 torchaudio의 공식 문서를 참고하시면 더 많은 정보를 얻을 수 있습니다:

제 답변이 정확하지 않을 수도 있으니, 문제 해결에 참고하시되 추가적인 검증이 필요할 수 있습니다. 추가적인 질문이나 궁금한 점이 있으시면 언제든지 질문해주세요!


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 Google의 Gemini Pro 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요. 질문을 이해했고, DCT를 사용하여 멜 스펙트로그램을 생성하는 방법에 대해 설명해 드리겠습니다.

  1. 라이브러리 로딩
    먼저 필요한 라이브러리를 임포트합니다.

    import torch
    from torchaudio.transforms import MelSpectrogram
    
  2. DCT 스펙트로그램 생성 함수
    sdct 함수를 사용하여 DCT 스펙트로그램을 생성하는 함수를 정의합니다.

    def dct_spectrogram(waveform, n_fft=4096, hop_length=1024, power=2.0):
        mel_spectrogram = MelSpectrogram(sample_rate=waveform.sample_rate, n_fft=n_fft, hop_length=hop_length, power=power)
        return mel_spectrogram(waveform)
    
  3. 멜 스케일 적용
    dct_spectrogram 함수에서 반환된 스펙트로그램에 멜 스케일을 적용합니다.

    def mel_scale(spectrogram):
        # 멜 스케일을 적용하는 코드를 여기에 작성합니다.
        return mel_spectrogram
    
  4. DCTMelspectrogram 클래스
    DCTMelspectrogram 클래스를 정의하여 DCT 스펙트로그램과 멜 스케일을 적용한 멜 스펙트로그램을 생성합니다.

    class DCTMelspectrogram(torch.nn.Module):
        def __init__(self, sample_rate=44100, n_fft=4096, hop_length=1024, power=2.0):
            super().__init__()
            self.dct_spectrogram = dct_spectrogram
            self.mel_scale = mel_scale
    
        def forward(self, waveform):
            spectrogram = self.dct_spectrogram(waveform)
            mel_spectrogram = self.mel_scale(spectrogram)
            return mel_spectrogram
    

이렇게 하면 DCT를 사용하여 멜 스펙트로그램을 생성할 수 있습니다.

자세한 내용은 다음 링크를 참조하세요.


  • 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!
  • 아래 답변은 OpenAI의 GPT-4 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
  • 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다. :sweat_smile:

안녕하세요, ojun.kwon님! 멜 스펙트로그램 생성 시 FFT 대신 DCT를 사용하여 음성 처리를 하고자 하는 문제에 대해 질문해주셨군요. 질문을 잘 이해했습니다. 여러분이 원하는 것은 기존의 STFT 과정에서 FFT 대신 DCT를 사용하여 스펙트로그램을 생성하고, 이를 멜 스케일로 변환하여 멜 스펙트로그램을 생성하는 클래스 DCTMelspectrogram을 작성하는 것으로 보입니다. 이 과정에서 실수 연산의 이점을 활용하고자 하시는군요.

이 문제를 해결하기 위해, 먼저 DCT를 사용하여 스펙트로그램을 생성하는 과정을 구현하셨고, 이제 해당 스펙트로그램에 멜 스케일을 적용하는 과정을 추가해야 합니다. PyTorch와 torchaudio 라이브러리를 활용하여 이를 구현할 수 있습니다. 아래는 DCTMelspectrogram 클래스를 작성하는 방법에 대한 예시 코드입니다.

import torch
import torchaudio
import numpy as np
from torch.nn import Module
from typing import Optional

# 여기에 이전에 정의한 sdct 및 spectrogram_dct 함수를 포함시킵니다.

class DCTMelspectrogram(Module):
    def __init__(self, 
                 sample_rate: int = 44100, 
                 n_fft: int = 4096, 
                 hop_length: int = 1024, 
                 n_mels: int = 128, # 멜 필터뱅크의 개수
                 power: Optional[float] = 2.0
                 ) -> None:
        super().__init__()
        self.sample_rate = sample_rate
        self.n_fft = n_fft
        self.hop_length = hop_length
        self.n_mels = n_mels
        self.power = power
        # 멜 스케일 변환을 위한 멜 필터뱅크 생성
        self.mel_filter = torchaudio.transforms.MelScale(n_mels=n_mels, 
                                                         sample_rate=sample_rate, 
                                                         n_stft=(n_fft // 2) + 1)

    def forward(self, waveform: torch.Tensor) -> torch.Tensor:
        # DCT 스펙트로그램 계산
        dct_spectrogram = spectrogram_dct(waveform, self.n_fft, self.hop_length, self.power)
        # 멜 스케일 적용
        mel_spectrogram = self.mel_filter(dct_spectrogram)
        return mel_spectrogram

위 코드에서 DCTMelspectrogram 클래스는 DCT를 사용하여 스펙트로그램을 생성한 후, torchaudio의 MelScale을 사용하여 멜 스케일로 변환합니다. MelScale은 주어진 스펙트로그램에 멜 필터뱅크를 적용하여 멜 스펙트로그램을 생성합니다. 이 클래스를 사용하면 원하는 멜 스펙트로그램을 얻을 수 있습니다.

이 예시 코드는 기본적인 구현을 보여주며, 실제 사용 시에는 파라미터를 조정하거나 추가적인 전처리 및 후처리 과정이 필요할 수 있습니다.

더 자세한 정보와 PyTorch 및 torchaudio의 사용법에 대해서는 공식 문서를 참고하시기 바랍니다:

제공된 코드와 설명이 도움이 되었기를 바랍니다. 추가적인 질문이나 궁금한 점이 있으시면 언제든지 질문해주세요. 제 답변이 정확하지 않을 수도 있으니, 문제 해결에 참고하시되 실제 적용 시에는 충분한 테스트를 거치시길 바랍니다.


  • 이 답변이 도움이 되셨나요? 괜찮았다고 생각하신다면 아래 :heart:를 한 번 눌러주시길 부탁드려요!

스펙트로 그램에 mel weight를 곱해야합니다
예시)

melmat = librosa.filters.mel( sr=16000, n_fft=512, n_mels=80,  fmin=0,  fmax=8000, htk=False)
logmel = torch.matmul(dct_spectrogram, melmat)
1개의 좋아요