open_Call_b2g();open_Call_g2b();

本文介绍了一种基于线性预测法的语音变调与变速技术,通过调整帧长、窗长、预测系数等参数,实现了语音的变调不变速及变速不变调效果。该技术包括了语音数据的读取、归一化、帧处理、预测、重建等多个步骤,最终通过合成激励信号和滤波器实现语音的变调和变速。实验结果显示,该方法能够有效地改变语音的音高和速度,为语音处理提供了新的思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

% --- Executes on button press in open_pushbutton.
function open_Call_b2g()
% hObject    handle to open_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[filename pathname]=uigetfile({'*.wav','ALL FILES(*.*)'},'选择声音文件');
if isequal([filename pathname],[0,0])
    return;
end
strname=[pathname filename];%选择的声音文件路径和文件名
[data Fs]=wavread(strname);%data表示声音数据 Fs表示频率
handles.y=data;
handles.Fs=Fs;
handles.yoriginal=data;
handles.foriginal=Fs;
%guidata(hObject,handles);
b2g_Call(handles);

% --- Executes on button press in b2g_pushbutton.
function b2g_Call(handles)
% hObject    handle to b2g_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
      %读取音频信息(双声道,16位,频率44100Hz)
      % 定义常数
    FL = 80;                % 帧长
    WL = 240;               % 窗长
    P = 10;                 % 预测系数个数
    data=handles.y;fs=handles.Fs;     % 载入语音数据
	data= data/max(data);	%归一化
    L = length(data);          % 读入语音长度
    FN = floor(L/FL)-2;     % 计算帧数
    
	% 预测和重建滤波器
    exc = zeros(L,1);       % 激励信号(预测误差)
    zi_pre = zeros(P,1);    % 预测滤波器的状态
    s_rec = zeros(L,1);     % 重建语音
    zi_rec = zeros(P,1);
    
	% 合成滤波器
    exc_syn = zeros(L,1);   % 合成的激励信号(脉冲串)
    s_syn = zeros(L,1);     % 合成语音
	last_syn = 0;   %存储上一个(或多个)段的最后一个脉冲的下标
	zi_syn = zeros(P,1);   % 合成滤波器的状态
    
	% 变调不变速滤波器
    exc_syn_t = zeros(L,1);   % 合成的激励信号(脉冲串)
    s_syn_t = zeros(L,1);     % 合成语音
	last_syn_t = 0;   %存储上一个(或多个)段的最后一个脉冲的下标
	zi_syn_t = zeros(P,1);   % 合成滤波器的状态
    
	% 变速不变调滤波器(假设速度减慢一倍)
	
    hw = hamming(WL);       % 汉明窗
    
    % 依次处理每帧语音
    for n = 3:FN

        % 计算预测系数(不需要掌握)
        s_w = data(n*FL-WL+1:n*FL).*hw;    %汉明窗加权后的语音
        [A E] = lpc(s_w, P);            %用线性预测法计算P个预测系数
                                        % A是预测系数,E会被用来计算合成激励的能量

      
        
        s_f = data((n-1)*FL+1:n*FL);       % 本帧语音,下面就要对它做处理

        % (4) 用filter函数s_f计算激励,注意保持滤波器状态
		[exc1,zi_pre] = filter(A,1,s_f,zi_pre);
        
        exc((n-1)*FL+1:n*FL) = exc1; %计算得到的激励

        % (5) 用filter函数和exc重建语音,注意保持滤波器状态
		[s_rec1,zi_rec] = filter(1,A,exc1,zi_rec);
        
        s_rec((n-1)*FL+1:n*FL) = s_rec1; %计算得到的重建语音

        % 注意下面只有在得到exc后才会计算正确
        s_Pitch = exc(n*FL-222:n*FL);
        PT = findpitch(s_Pitch);    % 计算基音周期PT(不要求掌握)
        G = sqrt(E*PT);           % 计算合成激励的能量G(不要求掌握)

        		
		%方法3:本段激励只能修改本段长度
		tempn_syn = [1:n*FL-last_syn]';
		exc_syn1 = zeros(length(tempn_syn),1);
		exc_syn1(mod(tempn_syn,PT)==0) = G; %某一段算出的脉冲
		exc_syn1 = exc_syn1((n-1)*FL-last_syn+1:n*FL-last_syn);
		[s_syn1,zi_syn] = filter(1,A,exc_syn1,zi_syn);
		exc_syn((n-1)*FL+1:n*FL) =  exc_syn1;   %计算得到的合成激励
		s_syn((n-1)*FL+1:n*FL) = s_syn1;   %计算得到的合成语音
		last_syn = last_syn+PT*floor((n*FL-last_syn)/PT);
 		
       
        
        % (13) 将基音周期减小一半,将共振峰频率增加150Hz,重新合成语音,听听是啥感受~
		PT1 =floor(PT/2);   %减小基音周期
        poles = roots(A);
		deltaOMG =150*2*pi/fs;
		for p=1:10   %增加共振峰频率,实轴上方的极点逆时针转,下方顺时针转
			if imag(poles(p))>0 poles(p) = poles(p)*exp(j*deltaOMG);
			elseif imag(poles(p))<0 poles(p) = poles(p)*exp(-j*deltaOMG);
			end
		end
		A1=poly(poles);
	
		
		tempn_syn_t = [1:n*FL-last_syn_t]';
		exc_syn1_t = zeros(length(tempn_syn_t),1);
		exc_syn1_t(mod(tempn_syn_t,PT1)==0) = G; %某一段算出的脉冲
		exc_syn1_t = exc_syn1_t((n-1)*FL-last_syn_t+1:n*FL-last_syn_t);
		[s_syn1_t,zi_syn_t] = filter(1,A1,exc_syn1_t,zi_syn_t);
		exc_syn_t((n-1)*FL+1:n*FL) =  exc_syn1_t;   %计算得到的合成激励
		s_syn_t((n-1)*FL+1:n*FL) = s_syn1_t;   %计算得到的合成语音
		last_syn_t = last_syn_t+PT1*floor((n*FL-last_syn_t)/PT1);
        
    end   %循环结束,获得变换后语音 s_syn_t
% 
%      plot(handles.axes3,s_syn_t),
%      set(handles.axes3,'Xgrid','on');
%      set(handles.axes3,'Ygrid','on');
%      xlabel(handles.axes3,'数据序列');
%      ylabel(handles.axes3,'频率');
%      title(handles.axes3,'变音后的时域图'),XLim([0,length(s_syn_t)]);	
% 
     subplot(1,3,3);plot(s_syn_t),
     grid on;
     xlabel('数据序列');
     ylabel('频率');
     title('变音后的时域图'),XLim([0,length(s_syn_t)]);	

     handles.y=s_syn_t;
%      guidata(hObject,handles);
     Fs=handles.foriginal;  
     N=length(handles.y);
    y1=fft(handles.y,N);
    f1=0:Fs/N:Fs*(N-1)/N;
%     plot(handles.axes1,f1,handles.yoriginal);
%     title(handles.axes1,'原始时域图');
%     xlabel(handles.axes1,'时间');
%     ylabel(handles.axes1,'频率');
%     set(handles.axes1,'Xgrid','on');
%     set(handles.axes1,'Ygrid','on');
%
    subplot(1,3,1);plot(f1,handles.yoriginal);
    title('原始时域图');
    xlabel('时间');
    ylabel('频率');
    grid on;

    
%     plot(handles.axes2,f1(1:N/2),y1(1:N/2));
%     set(handles.axes2,'Xgrid','on');
%     set(handles.axes2,'Ygrid','on');
%     title(handles.axes2,'频谱图');
%     xlabel( handles.axes2,'频率');
%     ylabel( handles.axes2,'幅度');
%
    subplot(1,3,2);plot(f1(1:N/2),y1(1:N/2));
    grid on;
    title('频谱图');
    xlabel('频率');
    ylabel('幅度');

   pause(3);
   sound(handles.yoriginal);
   sound(handles.y);

  % 计算一段语音的基音周期
function PT = findpitch(s)
[B, A] = butter(5, 700/4000);
s = filter(B,A,s);
R = zeros(143,1);
for k=1:143
    R(k) = s(144:223)'*s(144-k:223-k);
end
[R1,T1] = max(R(80:143));
T1 = T1 + 79;
R1 = R1/(norm(s(144-T1:223-T1))+1);
[R2,T2] = max(R(40:79));
T2 = T2 + 39;
R2 = R2/(norm(s(144-T2:223-T2))+1);
[R3,T3] = max(R(20:39));
T3 = T3 + 19;
R3 = R3/(norm(s(144-T3:223-T3))+1);
Top = T1;
Rop = R1;
if R2 >= 0.85*Rop
    Rop = R2;
    Top = T2;
end
if R3 > 0.85*Rop
    Rop = R3;
    Top = T3;
end
PT = Top;
return

   


% --- Executes on button press in open_pushbutton.
function open_Call_g2b()
% hObject    handle to open_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[filename pathname]=uigetfile({'*.wav','ALL FILES(*.*)'},'选择声音文件');
if isequal([filename pathname],[0,0])
    return;
end
strname=[pathname filename];%选择的声音文件路径和文件名
[data Fs]=wavread(strname);%data表示声音数据 Fs表示频率
handles.y=data;
handles.Fs=Fs;
handles.yoriginal=data;
handles.foriginal=Fs;
%guidata(hObject,handles);
g2b_Call(handles);

% --- Executes on button press in g2b_pushbutton.
function g2b_Call(handles)
% hObject    handle to g2b_pushbutton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
 y=handles.y;
 fs=handles.Fs;%读取音频信息(双声道,16位,频率44100Hz)
N=length(y)
% f=0:fs/N:fs*(N-1)/N;
f=[0:N-1]*fs/N;
Y=fft(y,N);    %进行傅立叶变换=>Y
%plot(handles.axes2,f(1:N/2),Y(1:N/2));
% title(handles.axes2,'声音信号的频谱');
% xlabel(handles.axes2,'频率');
% ylabel(handles.axes2,'振幅');
subplot(1,3,2);plot(f(1:N/2),Y(1:N/2));
title('声音信号的频谱');
xlabel('频率');
ylabel('振幅');
grid on;
% f1=0:(fs*0.7)/N:(fs*0.7)*(N-1)/N;
f1=[0:N-1]*(fs*0.7)/N;%降低频率为原频率f的0.7
% syms t;
t=[0,9];
R=y*exp(2*pi*300*t);%改变声音数据y=>R
P=fft(R,N);%y =>R , 傅立叶变换=>P
Z=ifft(P);
% z=real(Z);
handles.y=y; % y根本就没有变化啊?
% plot(handles.axes3,f1(1:N/2),Z(1:N/2));
% title(handles.axes3,'变声后的时域图');
% xlabel(handles.axes3,'时间序列');
% ylabel(handles.axes3,'频率')
% set(handles.axes3,'Xgrid','on');
% set(handles.axes3,'Ygrid','on');
subplot(1,3,3);plot(f1(1:N/2),Z(1:N/2));
title('变声后的频谱');
xlabel('频率');
ylabel('幅值')
grid on;

 Fs=handles.foriginal;  
    N=length(handles.y);
    y1=fft(handles.y,N);
%     f1=0:Fs/N:Fs*(N-1)/N;
    f1=[0:N-1]*Fs/N;
%     plot(handles.axes1,f1,handles.yoriginal);
%     title(handles.axes1,'原始时域图');
%     xlabel(handles.axes1,'时间');
%     ylabel(handles.axes1,'频率');
%     set(handles.axes1,'Xgrid','on');
%     set(handles.axes1,'Ygrid','on');
   subplot(1,3,1); plot(f1,handles.yoriginal);
    title('原始的频谱?');
    xlabel('频率');
    ylabel('幅值');
    grid on;
   
    
%     plot(handles.axes2,f1(1:N/2),y1(1:N/2));
%     set(handles.axes2,'Xgrid','on');
%     set(handles.axes2,'Ygrid','on');
%     title(handles.axes2,'频谱图');
%     xlabel( handles.axes2,'频率');
%     ylabel( handles.axes2,'幅度');
    figure;plot(f1(1:N/2),y1(1:N/2));
    grid on;
    title('频谱图');
    xlabel('频率');
    ylabel('幅度');

   pause(3);
%guidata(hObject,handles);

sound(handles.yoriginal);
sound(handles.y,handles.foriginal*0.7);


/* * SEMIDRIVE Copyright Statement * Copyright (c) SEMIDRIVE. All rights reserved * This software and all rights therein are owned by SEMIDRIVE, * and are protected by copyright law and other relevant laws, regulations and protection. * Without SEMIDRIVE’s prior written consent and /or related rights, * please do not use this software or any potion thereof in any form or by any means. * You may not reproduce, modify or distribute this software except in compliance with the License. * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * You should have received a copy of the License along with this program. * If not, see <http://www.semidrive.com/licenses/>. */ #ifndef __SDRV_G2D_H__ #define __SDRV_G2D_H__ #include <linux/platform_device.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/miscdevice.h> #include <linux/list.h> #include <asm/io.h> #include <linux/iommu.h> #include <linux/wait.h> #include <uapi/drm/drm_fourcc.h> #include <uapi/drm/sdrv_g2d_cfg.h> #include "g2d_common.h" #define PR_INFO pr_info #define ERROR pr_err typedef unsigned long int addr_t; #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif extern int debug_g2d; #define G2D_INFO(fmt, args...) do {\ PR_INFO("[g2d] [%20s] " fmt, __func__, ##args);\ }while(0) #define G2D_DBG(fmt, args...) do {\ if (debug_g2d >= 1) {\ PR_INFO("[g2d] <%d> [%20s] " fmt, __LINE__, __func__, ##args);}\ }while(0) #define G2D_ERROR(fmt, args...) ERROR("[g2d] <%d> [%20s] Error: " fmt, __LINE__, __func__, ##args) #define DDBG(x) G2D_DBG(#x " -> %d\n", x) #define XDBG(x) G2D_DBG(#x " -> 0x%x\n", x) #define PDBG(x) G2D_DBG(#x " -> %p\n", x) #define ENTRY() G2D_DBG("call <%d>\n", __LINE__) #define GP_ECHO_NAME "g2d_gpipe_echo" #define GP_MID_NAME "g2d_gpipe_mid" #define GP_HIGH_NAME "g2d_gpipe_high" #define SPIPE_NAME "g2d_spipe" #define G2D_NR_DEVS 4 /*Kunlun DP layer format TILE vsize*/ enum { TILE_VSIZE_1 = 0b000, TILE_VSIZE_2 = 0b001, TILE_VSIZE_4 = 0b010, TILE_VSIZE_8 = 0b011, TILE_VSIZE_16 = 0b100, }; /*Kunlun DP layer format TILE hsize*/ enum { TILE_HSIZE_1 = 0b000, TILE_HSIZE_8 = 0b001, TILE_HSIZE_16 = 0b010, TILE_HSIZE_32 = 0b011, TILE_HSIZE_64 = 0b100, TILE_HSIZE_128 = 0b101, }; /**/ enum { FBDC_U8U8U8U8 = 0xc, FBDC_U16 = 0x9, FBDC_R5G6B5 = 0x5, FBDC_U8 = 0x0, FBDC_NV21 = 0x37, FBDC_YUV420_16PACK = 0x65 }; enum kunlun_plane_property { PLANE_PROP_ALPHA, PLANE_PROP_BLEND_MODE, PLANE_PROP_FBDC_HSIZE_Y, PLANE_PROP_FBDC_HSIZE_UV, PLANE_PROP_CAP_MASK, PLANE_PROP_MAX_NUM }; enum { DRM_MODE_BLEND_PIXEL_NONE = 0, DRM_MODE_BLEND_PREMULTI, DRM_MODE_BLEND_COVERAGE }; enum { PLANE_DISABLE, PLANE_ENABLE }; enum { PROP_PLANE_CAP_RGB = 0, PROP_PLANE_CAP_YUV, PROP_PLANE_CAP_XFBC, PROP_PLANE_CAP_YUV_FBC, PROP_PLANE_CAP_ROTATION, PROP_PLANE_CAP_SCALING, }; enum { TYPE_GP_ECHO = 0, TYPE_GP_MID, TYPE_GP_HIGH, TYPE_SPIPE }; struct g2d_pipe; struct pipe_operation { int (*init)(struct g2d_pipe *); int (*set)(struct g2d_pipe *, int , struct g2d_layer *); void (*csc_coef_set)(struct g2d_pipe *, struct g2d_coeff_table *); }; struct g2d_pipe { void __iomem *iomem_regs; void __iomem *regs; unsigned long reg_offset; int id; // the ordered id from 0 struct sdrv_g2d *gd; const char *name; int type; struct pipe_operation *ops; struct g2d_pipe_capability *cap; struct g2d_pipe *next; }; struct g2d_monitor { int is_monitor; int is_init; ktime_t timeout; struct hrtimer timer; bool g2d_on_task; int occupancy_rate; int timer_count; int valid_times; int sampling_time; }; struct sdrv_g2d { struct platform_device *pdev; struct cdev cdev; struct miscdevice mdev; void __iomem *iomem_regs; void __iomem *regs; bool iommu_enable; struct iommu_domain *domain; struct mutex m_lock; struct wait_queue_head wq; bool frame_done; int id; const char *name; int irq; int write_mode; cmdfile_info cmd_info[G2D_CMDFILE_MAX_NUM]; unsigned long dma_buf; const struct g2d_ops *ops; struct g2d_capability cap; struct g2d_pipe *pipes[PIPE_MAX]; int num_pipe; int du_inited; struct g2d_monitor monitor; }; struct g2d_ops { int (*init)(struct sdrv_g2d *); int (*enable)(struct sdrv_g2d*, int); int (*reset)(struct sdrv_g2d *); int (*mlc_set)(struct sdrv_g2d *, int , struct g2d_input *); int (*fill_rect)(struct sdrv_g2d *, struct g2d_bg_cfg *, struct g2d_output_cfg *); int (*fastcopy)(struct sdrv_g2d *, addr_t , u32 , u32 , u32 , addr_t , u32); int (*config)(struct sdrv_g2d *); int (*irq_handler)(struct sdrv_g2d *); int (*rwdma)(struct sdrv_g2d *, struct g2d_input *); void (*close_fastcopy)(struct sdrv_g2d *); int (*wpipe_set)(struct sdrv_g2d *, int, struct g2d_output_cfg *); int (*check_stroke)(struct g2d_input *); int (*scaler_coef_set)(struct sdrv_g2d *, struct g2d_coeff_table *); }; struct sdrv_g2d_data { const char *version; const struct g2d_ops* ops; }; struct ops_entry { const char *ver; void *ops; }; int g2d_get_capability(struct g2d_capability *cap); unsigned int get_compval_from_comp(struct pix_g2dcomp *comp); unsigned int get_frm_ctrl_from_comp(struct pix_g2dcomp *comp); int sdrv_wpipe_pix_comp(uint32_t format, struct pix_g2dcomp *comp); int sdrv_pix_comp(uint32_t format, struct pix_g2dcomp *comp); bool g2d_format_is_yuv(uint32_t format); int g2d_format_wpipe_bypass(uint32_t format); struct ops_list { struct list_head head; struct ops_entry *entry; }; extern struct list_head g2d_pipe_list_head; int g2d_ops_register(struct ops_entry *entry, struct list_head *head); void *g2d_ops_attach(const char *str, struct list_head *head); #define g2d_pipe_ops_register(entry) g2d_ops_register(entry, &g2d_pipe_list_head) #define g2d_pipe_ops_attach(str) g2d_ops_attach(str, &g2d_pipe_list_head) int g2d_choose_pipe(struct sdrv_g2d *gd, int hwid, int type, uint32_t offset); struct sdrv_g2d *get_g2d_by_id(int id); extern struct ops_entry gpipe_mid_g2d_entry; extern struct ops_entry gpipe_high_g2d_entry; extern struct ops_entry spipe_g2d_entry; #endif //__SDRV_G2D_H__ 请提供以上代码详细的中文注释,包括函数声明、结构体成员、枚举成员等。
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值