음악 분류 딥러닝을 만들자(4) - 객체지향

응큼한포도·2024년 6월 16일
1

이왕 할 거 재대로 만들자

부트캠프에서 자바를 배우며 객체지향적으로 만드는 걸 배웠는 데 머신러닝 프로젝트에서도 적용 해보자.

환경

IDE - Pycharm
python - 3.11
stack - librosa, pytorch, pandas, anaconda

프로젝트 구조

vocal_classification_using_CNN/
├── configs/
├── data/
├── src/
│   ├── evaluations/
│   ├── models/
│   └── preprocessing/
│       └── convert_to_wav.py
└── tests/
    ├── evaluations/
    ├── models/
    └── preprocessing/
        └── test_convert_to_wav.py

소스 코드

import os
import torchaudio

class ConvertToWav:
    def __init__(self, file_path, folder_path):
        self.file_path = file_path
        self.folder_path = folder_path

    def convert_and_save(self):
        waveform, sr = torchaudio.load(self.file_path)
        wav_file_path = os.path.splitext(self.file_path)[0] + ".wav"
        torchaudio.save(wav_file_path, waveform, sr)

    def is_supported_file(self, file_name):
        supported_extensions = ['.mp3', '.mp4', '.wav', '.flac', '.ogg']
        return any(file_name.lower().endswith(ext) for ext in supported_extensions)

    def convert_files(self):
        if not os.path.exists(self.folder_path):
            raise ValueError(f"{self.folder_path}은(는) 폴더가 아닙니다.")

        file_list = os.listdir(self.folder_path)

        for file in file_list:
            file_path = os.path.join(self.folder_path, file)
            if os.path.isfile(file_path) and self.is_supported_file(file):
                self.file_path = file_path
                self.convert_and_save()

소스 코드는 저번에 작성한 모든 음원을 wav파일로 바꾸는 코드를 객체지향적으로 바꾸려 노력했다.

클래스는 wav파일로 바꾸는 단 하나의 책임을 가진다.

각각의 코드는
1. 단위 파일을 wav로 바꾸고 저장
2. 폴더 안에 음원이 있는지 확인
3. 폴더안의 파일에 1.을 적용

테스트 코드

import sys
import os
import unittest
import wave
import numpy as np

# 현재 파일의 경로에서 src 디렉토리까지의 절대 경로를 sys.path에 추가
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../src')))

# ConvertToWav 클래스를 import
from preprocessing.convert_to_wav import ConvertToWav


# 간단한 WAV 파일 생성 함수
def create_test_wav(filename):
    sample_rate = 44100  # 44.1 kHz
    duration = 1  # 1 second
    frequency = 440.0  # 440 Hz (A4)

    with wave.open(filename, 'w') as wav_file:
        n_channels = 1
        sampwidth = 2
        n_frames = sample_rate * duration
        comptype = "NONE"
        compname = "not compressed"
        wav_file.setparams((n_channels, sampwidth, sample_rate, n_frames, comptype, compname))

        t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
        data = (np.sin(2 * np.pi * frequency * t) * 32767).astype(np.int16)

        wav_file.writeframes(data.tobytes())


class TestConvertToWav(unittest.TestCase):

    def test_convert_to_wav(self):
        test_dir = "test_directory"
        temp_file_path = os.path.join(test_dir, "test_audio.mp3")

        # Create a directory for the test if it does not exist
        if not os.path.exists(test_dir):
            os.makedirs(test_dir)

        # Create a temporary test audio file
        create_test_wav(temp_file_path)

        # Create an instance of ConvertToWav
        converter = ConvertToWav(file_path=temp_file_path, folder_path=test_dir)

        # Call the convert_and_save method
        converter.convert_and_save()

        # Assert that the WAV file has been created
        wav_file_path = os.path.splitext(temp_file_path)[0] + ".wav"
        self.assertTrue(os.path.exists(wav_file_path))

        # Clean up: Delete the temporary test files
        os.remove(temp_file_path)
        os.remove(wav_file_path)
        os.rmdir(test_dir)


if __name__ == "__main__":
    unittest.main()

테스트 코드의 wav 파일 생성 매서드는 아마 재사용할 것 같은데 일단을 저기에 박아놨다. 추후에 테스트 코드에 코드 재사용하는 법을 익히고 분리할 것 이다.

깃허브

https://github.com/B-Singularity/Vocal-Classification-Using-CNN/tree/feat/preprocessing

앞으로 올린 모든 코드는 위 저장소에 있다.

profile
미친 취준생

0개의 댓글