| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 | #!usr/bin/env python# -*- coding: utf-8 -*-# author: kuangdd# date: 2019/12/22"""### audio_changer变声器,变高低音,变语速,变萝莉音,回声。"""from pathlib import Pathimport logginglogging.basicConfig(level=logging.INFO)logger = logging.getLogger(Path(__name__).stem)import numpy as npimport librosafrom .audio_io import _srdef change_pitch(wav, sr=_sr, rate=0.):    """    调音高。    :param rate:-20~20,float,0:原声    :param wav:    :param sr:    :return:    """    return librosa.effects.pitch_shift(wav, sr=sr, n_steps=rate)def change_speed(wav, sr=_sr, rate=0.):    """    调语速。    :param rate:0~5,float,0:原声    :param wav:    :param sr:    :return:    """    return librosa.effects.time_stretch(wav, rate)def change_sample(wav, sr=_sr, rate=1):    """    调采样率,语速和音高同时改变。    :param rate:0~5,float,1:原声    :param wav:    :param sr:    :return:    """    return librosa.resample(wav, orig_sr=sr, target_sr=int(sr * rate))def change_reback(wav, sr=_sr, rate=1):    """    回声。    :param rate:1~10,int,1:原声    :param wav:    :param sr:    :return:    """    frequencies, D = librosa.ifgram(wav, sr=sr)    D = pool(D, size=(1, rate))    D = repeat(D, rate)    return librosa.istft(D)def change_pitchspeed(wav, sr=_sr, rate=1):    """    音高和语速同时变化。    :param rate:0~10,float,1:原声    :param wav:    :param sr:    :return:    """    frequencies, D = librosa.ifgram(wav, sr=sr)    n = int(D.shape[0] * rate)    if n <= D.shape[0]:        D = drop(D, D.shape[0] - n, mode="r")    else:        D = rewardshape(D, (n, D.shape[1]))    return librosa.istft(D)def change_attention(wav, sr=_sr, rate=0):    """    突出高音或低音段。    :param rate:-100~100,int,0:原声    :param wav:    :param sr:    :return:    """    frequencies, D = librosa.ifgram(wav, sr=sr)    D = roll(D, rate)    return librosa.istft(D)def change_male(wav, sr=_sr, rate=0):    """    变男声。    :param rate:0~1025,int,0,1,1025:原声    :param wav:    :param sr:    :return:    """    frequencies, D = librosa.ifgram(wav, sr=sr)    D = pool_step(D, rate)    return librosa.istft(D)def change_stretch(wav, sr=_sr, rate=1):    """    成倍拉伸延长。    :param rate:1~10,int,1:原声    :param wav:    :param sr:    :return:    """    frequencies, D = librosa.ifgram(wav, sr=sr)    D = spread(D, rate)    return librosa.istft(D)def change_vague(wav, sr=_sr, rate=1):    """    模糊。    :param rate:1~10,int,1:原声    :param wav:    :param sr:    :return:    """    frequencies, D = librosa.ifgram(wav, sr=sr)    D = pool(D, (1, rate))    D = spread(D, (1, rate))    return librosa.istft(D)class CheckStep(object):    def __init__(self, step):        self.step = step        self.index = 0    def __call__(self, *args):        self.index += 1        return self.index % self.step != 0def spread(D, size=(3, 3)):    """传播,重复每个数据点。"""    if isinstance(size, tuple):        if size[0] > 1:            D = np.repeat(D, size[0], axis=0)        if size[1] > 1:            D = np.repeat(D, size[1], axis=1)        if size[0] * size[1] > 1:            D = D / (size[0] * size[1])    elif isinstance(size, int):        D = np.repeat(D, size, axis=1)    return Ddef drop(D, n, mode="l"):    """丢弃,mode:left,right,side,center"""    if n == 0:        return D    if mode == "l":        return D[n:]    elif mode == "r":        return D[:-n]    elif mode == "s":        return D[n // 2:-(n // 2)]    elif mode == "c":        if n < len(D):            return np.vstack((D[:n // 2], D[-(n // 2):]))        else:            return ()    else:        raise AssertionErrordef repeat(D, n, axis=0):    """重复"""    return np.repeat(D, n, axis=axis)def roll(D, n):    """循环移动"""    return np.roll(D, n, axis=0)def rewardshape(D, shape):    """填充"""    x = shape[0] - D.shape[0]    y = shape[1] - D.shape[1]    if x > 0:        bottomlist = np.zeros([x, D.shape[1]])        D = np.r_[D, bottomlist]    if y > 0:        rightlist = np.zeros([D.shape[0], y])        D = np.c_[D, rightlist]    return Ddef pool_step(D, step):    """步长池化"""    _shape = D.shape    if step < 2:        return D    cs = CheckStep(step)    return rewardshape(np.array(list(filter(cs, D))), _shape)def pool(D, size=(3, 3), shapeed=False):    """池化"""    _shape = D.shape    if isinstance(size, tuple):        if size[1] > 1:            D = _pool(D, size[1])        if size[0] > 1:            D = _pool(D.T, size[0]).T    elif isinstance(size, int):        D = _pool(D.T, size).T    if shapeed:        D = rewardshape(D, _shape)    return Ddef _pool(D, poolsize):    """池化方法"""    x = D.shape[1] // poolsize    restsize = D.shape[1] % poolsize    if restsize > 0:        x += 1        rightlist = np.zeros([D.shape[0], poolsize - restsize])        D = np.c_[D, rightlist]    D = D.reshape((-1, poolsize))    D = D.sum(axis=1).reshape(-1, x)    return Dif __name__ == '__main__':    from aukit.audio_player import play_audio    path = r"C:/Users/jared/Downloads/hi.mp3"    y, sr = librosa.load(path)    # y = change_vague(3, y, sr)    # y = change_pitch(-6, y, sr)    # y = change_speed(0.5, y, sr)    # y = change_sample(0.8, y, sr)    # y = change_reback(3, y, sr)    # y = change_pitchspeed(2, y, sr)    # y = change_attention(50, y, sr)    # y = change_male(5, y, sr)    # y = change_vague(6, y, sr)    """童声"""    y = change_pitch(6, y, sr)    y = change_male(20, y, sr)    play_audio(y, sr=sr)
 |