UOMOP

Librosa - tempo contorl 본문

Project/Music Plagiarism Project

Librosa - tempo contorl

Happy PinGu 2022. 10. 9. 02:15

Tempo 확인하기

음원의 템포를 확인하기 위해서 librosa에서 제공하는 beat_track, tempo함수를 사용하였지만, 이상적인 결과를 확인하지 못하였다. flatness를 구해서 Spectral_Centroid의 Mean값으로 tempo를 확인하는 것이 더 이상적이다.

# ========================= 각종 함수 정의 =========================

def Devider(A, B, sr, period, mode) :
    # A    : 표절 논란곡 1
    # B    : 표절 논란곡 2
    # sr   : A, B의 Sampling Rate
    # period : 몇 초씩 쪼갤 것인가
    # mode = 1 : 전체 길이 데이터를 사용
    #      = 2 : 전체 길의의 1/2만을 사용 

    # ===== 두 곡의 길이를 동일하게 설정 =====
    length = int( ( min(len(A.tolist()), len(B.tolist())) ) / mode )
    A = (A[0 : length])
    B = (B[0 : length])

    # ===== 2곡의 Data를 몇 개로 dividing 할 것인지 확인 =====
    num_of_window =  math.floor(length / (period * sr))

    final_index_A = 0
    final_index_B = 0

    # ===== 각 곡의 dividing된 Data가 Mat_A, Mat_B에 2D-array로 save =====
    Mat_A = [[0 for col in range(period * sr)] for row in range(num_of_window)]
    Mat_B = [[0 for col in range(period * sr)] for row in range(num_of_window)]

    # ===== 각 곡의 dividing된 Data가 Mat_A, Mat_B에 2D-array로 save =====
    for i in range(0, num_of_window) :
        for j in range(0, period * sr) :
            Mat_A[i][j] = A[final_index_A  + j]
            Mat_B[i][j] = B[final_index_B  + j]
        final_index_A = (period * sr) * (i+1)
        final_index_B = (period * sr) * (i+1)

    return Mat_A, Mat_B


def extractor(A, area, sr) :
    # area = 01:31.05 ~ 02:18.32
    area = str(area)
    start = int(area[0]) * 600 + int(area[1]) * 60 + int(area[3]) * 10 + int(area[4]) * 1 + int(area[6]) /100
    end   = int(area[10]) * 600 + int(area[11]) * 60 + int(area[13]) * 10 + int(area[14]) * 1 + int(area[16]) /10
    A_cut = A[int(start * sr) : int(end * sr)]

    return A_cut

def get_features(y, sr) : # Categorizing label data
  
    chroma_shift = librosa.feature.chroma_stft(y, n_fft=2048, hop_length=512) # 음악의 크로마 특징
    rmse = librosa.feature.rms(y, frame_length=512, hop_length=512)           # RMS값
    spectral_centroids = librosa.feature.spectral_centroid(y, sr=sr)          # 스펙트럼 무게 중심
    spec_bw = librosa.feature.spectral_bandwidth(y, sr=sr)                    # 스펙트럼 대역폭
    spectral_rolloff = librosa.feature.spectral_rolloff(y, sr=sr)[0]          # rolloff
    zcr = librosa.feature.zero_crossing_rate(y, hop_length=512)               # zero to crossing
    y_harm, y_perc = librosa.effects.hpss(y)                                  # 하모닉, 충격파
    tempo, _ = librosa.beat.beat_track(y, sr=sr)                              # 템포
    mfcc = librosa.feature.mfcc(y, sr=sr,n_mfcc=20)                           # mfcc 20까지 추출

    features_extracted = np.hstack([                                    
                                    np.mean(chroma_shift),
                                    np.var(chroma_shift),
                                    np.mean(rmse),
                                    np.var(rmse),
                                    np.mean(spectral_centroids),
                                    np.var(spectral_centroids),
                                    np.mean(spec_bw),
                                    np.var(spec_bw),
                                    np.mean(spectral_rolloff),
                                    np.var(spectral_rolloff),
                                    np.mean(zcr),
                                    np.var(zcr),
                                    np.mean(y_harm),
                                    np.var(y_harm),
                                    np.mean(y_perc),
                                    np.var(y_perc),
                                    tempo,
                                    np.mean(mfcc.T, axis=0),
                                    np.var(mfcc.T, axis=0)
                                                            ])

    features = features_extracted.reshape(1, 57)

    col_name = ['chroma_stft_mean',   'chroma_stft_var', 'rms_mean', 'rms_var', 'spectral_centroid_mean', 'spectral_centroid_var', 'spectral_bandwidth_mean', 'spectral_bandwidth_var', 'rolloff_mean', 'rolloff_var', 'zero_crossing_rate_mean', 'zero_crossing_rate_var', 'harmony_mean', 'harmony_var', 'perceptr_mean', 'perceptr_var', 'tempo', 'mfcc1_mean', 'mfcc1_var', 'mfcc2_mean', 'mfcc2_var', 'mfcc3_mean', 'mfcc3_var', 'mfcc4_mean', 'mfcc4_var', 'mfcc5_mean',   'mfcc5_var', 'mfcc6_mean', 'mfcc6_var', 'mfcc7_mean', 'mfcc7_var', 'mfcc8_mean', 'mfcc8_var', 'mfcc9_mean', 'mfcc9_var', 'mfcc10_mean', 'mfcc10_var', 'mfcc11_mean', 'mfcc11_var', 'mfcc12_mean', 'mfcc12_var', 'mfcc13_mean', 'mfcc13_var', 'mfcc14_mean', 'mfcc14_var', 'mfcc15_mean', 'mfcc15_var', 'mfcc16_mean', 'mfcc16_var', 'mfcc17_mean', 'mfcc17_var', 'mfcc18_mean', 'mfcc18_var', 'mfcc19_mean', 'mfcc19_var', 'mfcc20_mean', 'mfcc20_var']      
    df = pd.DataFrame(features, columns = col_name)
    array = (np.array(features)).tolist()

    return df, array


def get_tempo(y, sr) :
    tempo, _ = librosa.beat.beat_track(y, sr=sr)      
    return tempo

def get_flatness(y, sr) :
    flatness = librosa.feature.spectral_flatness(y = y)
sr = 22050
A, sr = librosa.load('3-1.wav', sr = sr)  
A_plag_area = "00:39.5 ~ 00:45.5"

A_extracted = extractor(A, A_plag_area, sr)
A_flatness = librosa.feature.spectral_flatness(y = A_extracted)
#x_A = range(0, len(A_flatness[0]))

plt.plot((A_flatness[0]))
#plt.ylim([0, 0.15])
plt.show

Comments