예제 #1
0
def get_vocal(mix_file, bg_file, lyric_file, out_file="out.wav"):
    print("\ndeal with ---", bg_file, "---")
    # 讀audio檔
    mix, sr = librosa.load(mix_file, sr=None)
    bg, sr = librosa.load(bg_file, sr=None)

    # 取得前奏的時間
    l = lyric_parser.Lyric(lyric_file)
    time = l.get_time_before_vocal()

    # 單位變換,從ms換成sample
    time = ms2sample(time - 1000, sr)
    time = time // 2

    # 前處理
    mix = mute_start(mix)
    bg = mute_start(bg)

    # 計算位移,音量
    shift, vol = compute_t_v(mix, bg, time)

    # 前處理
    mix, bg = npp.pad_the_same(mix, bg)
    mix2 = npp.right_shift(mix, shift)

    # 訊號相減
    result = mix2 * vol - bg

    # try
    # result = mix2*1.5151645 - bg

    # 輸出
    librosa.output.write_wav(out_file, result, sr)
    librosa.output.cl
def get_vocal_mp3_void(mix_file, bg_file, lyric_file, out_file="out.mp3"):
    # card_sample = ['clear', 'shift', 'volume_ratio',
    #                'song_sr', 'bg_sr', 'result_sr',
    #                'song_duration', 'bg_duration', 'result_duration', 'result_norm_ave',
    #                'error_text']
    card = [' ', ' ', ' ',
            ' ', ' ', ' ',
            ' ', ' ', ' ', ' ', ' ']

    # 讀audio檔
    bg, sr_bg = librosa.load(bg_file, sr=None)
    mix, sr_mix = librosa.load(mix_file, sr=None)

    # TODO: plt
    # import matplotlib.pyplot as plt
    # mix1, sr_mix = librosa.load(mix_file, sr=None, duration=10)
    # bg1, sr_bg = librosa.load(bg_file, sr=None, duration=10)
    # import librosa.display as d
    # import matplotlib.pyplot as plt
    # plt.figure()
    # d.waveplot(mix1, sr=sr_mix)
    # plt.title('mix')
    # plt.figure()
    # d.waveplot(bg1, sr=sr_bg)
    # plt.title('bg')
    # ###

    song_duration = len(mix)
    bg_duration = len(bg)

    if sr_mix != sr_bg:
        card = [0, ' ', ' ',
                sr_mix, sr_bg, ' ',
                song_duration, bg_duration, ' ', ' ', 'sr not match']

        # 輸出result with norm_value_fileName,回傳card
        fn = os.path.basename(out_file)
        fn = "sr_NOTmatch_" + fn
        dn = os.path.dirname(out_file)
        dn = os.path.join(dn, "error")
        fn = os.path.join(dn, fn)

        # Write null file with only filename
        result = np.array([])
        np.savetxt(fn, result)

        return card
    elif sr_mix == 44100:
        # shift = -1728
        shift = 0
    elif sr_mix == 22050:
        # shift = -1728 / 2
        shift = 0
    else:
        card = [0, ' ', ' ',
                sr_mix, sr_bg, ' ',
                song_duration, bg_duration, ' ', ' ', 'get_vocal error of if(sr_mix != sr_bg) function']

        # 輸出result with norm_value_fileName,回傳card
        fn = os.path.basename(out_file)
        fn = "sr_NOTmatch_" + fn
        dn = os.path.dirname(out_file)
        dn = os.path.join(dn, "error")
        fn = os.path.join(dn, fn)

        # Write null file with only filename
        result = np.array([])
        np.savetxt(fn, result)

        # Write null file with only filename
        result = np.array([])
        np.savetxt(fn, result)

        return card

    # sr is coming~
    sr = sr_mix
    sr_result = sr

    # get intro time
    l = lyric_parser.Lyric(lyric_file)
    time = l.get_time_before_vocal()

    if time < 1000:
        card[0] = 0
        card[10] = 'lyric might have wrong start (intro time < 1000)'

        # 輸出result with norm_value_fileName,回傳card
        fn = os.path.basename(out_file)
        fn = "lyric_wrongSTART_" + fn
        dn = os.path.dirname(out_file)
        dn = os.path.join(dn, "error")
        fn = os.path.join(dn, fn)

        # Write null file with only filename
        result = np.array([])
        np.savetxt(fn, result)

        return card

    # change ms 2 sample rate
    time = ms2sample(time - 1000, sr)
    time = time // 2

    # mute start to avoid blast sound
    mix = mute_start(mix)
    bg = mute_start(bg)

    # calculate volume rate
    vol, bg_norm = compute_vol_ratio_bgNorm(mix, bg, time)

    # some preprocessing and shift
    mix, bg = npp.pad_the_same(mix, bg)
    mix_shift = npp.right_shift(mix, shift)

    # devocal
    result = mix_shift[:song_duration] * vol - bg[:song_duration]
    # avoid lst blast (1728+1000)
    result = result[:len(result) - 3000]
    result_duration = len(result)

    # clear or not
    result_norm = linalg.norm(result[:time], ord=1)
    result_norm_ave = result_norm / time
    result_norm_ave = int(result_norm_ave * 10000000)

    if result_norm < bg_norm:

        fn = os.path.basename(out_file)
        fn = str(int(result_norm_ave)) + "_" + fn
        dn = os.path.dirname(out_file)
        dn = os.path.join(dn, "perfect")
        fn = os.path.join(dn, fn)

        # TODO : ouput result mp3
        write_arr_mp3(fn, result, sr)

        print(
            "   result_norm < bg_norm * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! ! ! de success ! ! !",
            end=" ")
        print(datetime.datetime.now())
        card = [1, shift, vol,
                sr_mix, sr_bg, sr_result,
                song_duration, bg_duration, result_duration, result_norm_ave, ' ']
        return card
    else:
        # 輸出result with norm_value_fileName,回傳card
        fn = os.path.basename(out_file)
        fn = "norm_" + str(int(result_norm_ave)) + "_" + fn
        dn = os.path.dirname(out_file)
        dn = os.path.join(dn, "error")
        fn = os.path.join(dn, fn)

        # Write null file with only filename
        result = np.array([])
        np.savetxt(fn, result)

        # write_arr_mp3(fn, result, sr)
        print("   " + fn)

        print(
            "   result_norm > bg_norm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! ! ! de fail ! ! !",
            end=" ")
        print(datetime.datetime.now())
        card = [0, shift, vol,
                sr_mix, sr_bg, sr_result,
                song_duration, bg_duration, result_duration, result_norm_ave, 'de fail']
        return card