wav音频文件的提取和分析(matlab)

WAV文件格式的介绍:WAV文件是计算机中最常见的存放声音的格式,其扩展名为.wav。WAV文件以RIFF(Resource interchange file format)档案的格式存储,含有不定长度的文件头(header)和数据(data),组成不定长度的区块(chunk)和子区块(sub-chunks)。
WAV文件可以分为三个子区块(chunk):

分区名称文件长度
RIFF chunk12 bytes
”fmt” sub-chunk可变长度, 16 bytes + extra
”data” sub-chunk可变长度, size of sample data

辅助函数:将wav文件中读取的16进制转为10进制。

% A表示wav文件数据
% start表示起始位
% total表示总位数
% return 得到的十进制数
function tmp = add_helper(A,start,total)
    tmp = A(start+total-1);
    for i=total-2:-1:0
        tmp = tmp*16*16+A(start+i);
    end
end

(1)采样频率:也称采样速度或采样率。定义了声音信号在“模拟-数字”转化过程中,单位时间内从连续信号中提取并组成离散信号的采样个数。它用赫兹(Hz)表示。

%法一:matlab的audioread函数返回的第二个参数即为采样频率
[~,fs] = audioread([path,file]);

%法二:直接读取wav文件的28位到25位四位数据即为采样频率
fs = add_helper(A,25,4);

(2)声道数:

%法一:matlab的audioread函数会将声道数转换为列数
channels_num = size(x,2);

%法二:直接读取wav文件的24位到23位即为声道数
channels_num = add_helper(A,23,2);%在第24和23位,24位为高位

(3)样本位数:也称采样位数,即对声音的辨析度。8位或16位,8位采样将取样信号分为256份;16位采样将取样信号分为65536份。

%法一:通过matlab的库函数audioinfo读取
info = audioinfo([path,file]);
bits_per_sample =info.BitsPerSample;
disp(['采样位数为',int2str(bits_per_sample)]);

%法二:直接读取wav文件的36位到35位两位即为样本位数
bits_per_sample = add_helper(A,35,2);

(4)求文件长:即音频文件所占用的内存空间,这里以KB为单位。

%法一:通过matlab的dir函数读取
D = dir([path,file]);
[file_length,file_length_type] = calculate_file_len(D.bytes);
fprintf('文件长为%.2f %s\n',file_length,file_length_type);

%法二:直接计算得到文件长度,简单进行单位换算
[file_length,file_length_type] = calculate_file_len(length(A));
fprintf('文件长为%.2f %s\n',file_length,file_length_type);

(5)求数据长:即WAV文件中,data子区块所包含的数据的长度,也以KB为单位。

%法一:乘以2的原因是在调用audioread函数时matlab自动将2Byte数据转化为了一个数据,实际数据长度是x长度的两倍
fprintf('数据长为%.2fKB\n',2*length(x)/1024);

%法二:直接读取WAV文件的78位到75位的四位数据即为数据部分的长度
data_length = add_helper(A,75,4);
[file_length,file_length_type] = calculate_file_len(data_length);
fprintf('数据长为%.2f %s\n',file_length,file_length_type);

(6)求数码率:表示单位时间(1秒)内传送的比特数bps(bit per second,位/秒),比特率越高质量越好,声音越饱满。码率=采样率×每次采样得到的样本位数×声道数。如果单位一般是k,码率(kbps)=码率(bps)/1000。

%波形数据传输速率(每秒平均字节数) = 采样频率 × 音频通道数 × 每次采样得到的样本位数 / 8
%比特率(kbs) = 波形数据传输速率 × 8 / 1000,除以1000是因为单位是k
kbps = fs * max_track_number * info.BitsPerSample / 8 * 8 / 1000;
fprintf('数码率为%.2f\n',kbps);

(7)求音频文件长度:音频持续的时间,可以通过数据长/采样率计算得到。

%法一:直接调用Matlab的Duration函数
fprintf('音频文件的长度为%.2f\n',info.Duration);

%直接计算,单声道数据长度除以采样率即为音频文件长度
info.music_length = roundn(info.real_length/info.fs,-2);

(8)显示李萨如图形:(8)将两个声道的数据分别加至示波器的Y轴输入端和x轴输入端,将出现一个合成图形,这个图形就是李沙育图形。
李沙育图形随两个输入信号的频率、相位、幅度不同,所呈现的波形也不同。当两个信号相位差为90°时,合成图形为正椭圆,此时若两个信号的振幅相同的话,合成图形为圆;当两个信号相位差为0°时,合成图形为直线,此时若两个信号振幅相同则为与x轴成45°的直线 。

%因为李萨如图形是将信号以左声道作为x轴数据,以右声道数据作为y轴数据,因此至少要双声道
if channels_num >= 2
    figure('Name','李萨如图形','NumberTitle','off');
    plot(x(:,1),x(:,2));
    title('李萨图图形','FontSize',20);
end

(9)实现音频播放功能:

choice = input('请选择使用左声道1播放还是右声道2:');
%法一:通过audioplayer函数实现播放
player = audioplayer(x(:,choice),fs);
play(player)%该函数既可以实现播放
pause(player)%该函数既可以实现暂停播放
resume(player)%该函数可以实现暂停后恢复播放
stop(player)%该函数可以实现停止播放

%法二:通过sound函数实现播放
sound(x(choice),fs);

(10)绘制波形图:

%法一:matlab的audioread函数会将声道数转换为列数
channels_num = size(x,2);
figure('Name','波形图形','NumberTitle','off');
for i = 1:track_number
    subplot(track_number,1,i);
    %横坐标表示序号,纵坐标表示归一化的频率值
    plot(x(:,i));
    title(['\fontsize{16}第',int2str(i),'声道']);
end

具体代码:
代码一:这个函数基本是通过调用matlab库函数实现的。
可以实现播放.wav文件;
可以选择文件;
显示波形图(单声道,双声道);
在波形图上显示声道数、采样频率、样本位数、文件长、数据长、数码率及音频文件长度等参数;
显示李沙育波形图;
可以选择声道播放。

clc;
clear;
close all;

%这里请自己设置路径,这里是以打开文件夹自己选择文件的方式
[file,path] = uigetfile('语音素材/wav_file.wav','*.wav');
if isequal(file,0)
    disp('没有选择文件')
else
    disp(['选择了文件',file])
end
%fs为采样率
info = audioinfo([path,file]);
[x,fs] = audioread([path,file]);

%最大声道数
channels_num = size(x,2);
choice = input('请选择使用左声道1播放还是右声道2还是双声道3:');
if choice == 1
    sound(x(:,1),fs);
elseif choice == 2
    sound(x(:,2),fs);
else
    sound(x(:,1:2),fs);
end

%选择声道数
track_number = input(['总声道数为',int2str(channels_num),'请输入需要的声道数:']);
while track_number>channels_num
    disp(['超出范围',int2str(channels_num),'请重新输入']);
    track_number = input('请输入需要的声道数:');
end

figure('Name','波形图形','NumberTitle','off');
for i = 1:track_number
    subplot(track_number,1,i);
    %横坐标表示序号,纵坐标表示归一化的频率值
    plot(x(:,i));
    title(['\fontsize{16}第',int2str(i),'声道']);
end

if channels_num >= 2
    figure('Name','李萨如图形','NumberTitle','off');
    plot(x(:,1),x(:,2));
    title('李萨图图形','FontSize',20);
end

%%
%获取相关信息
disp(['采样率为',int2str(fs)]);

disp(['声道数为',int2str(channels_num)]);

%需要获取文件本身的内容
%typec = class(x);
%fprintf(['采样位数为',typec(1,4:end),'\n']);
disp(['采样位数为',int2str(info.BitsPerSample)]);

%fprintf('音频文件的长度为%.2f\n',size(x,1)/fs);
fprintf('音频文件的长度为%.2f\n',info.Duration);

D = dir([path,file]);
fprintf('文件长为%dKB\n',round(D.bytes/1024));

%乘以2的原因是length(x)并不是真正数据的长度因为一个采样是需要16位,占两个byte
%而wav文件中给出的也是占用的byte数,而非通过audioread函数将16位数据自动换算为float
fprintf('数据长为%.2fKB\n',4*length(x)/1024);

%波形数据传输速率(每秒平均字节数) = 采样频率 × 音频通道数 × 每次采样得到的样本位数 / 8
%比特率(kbs) = 波形数据传输速率 × 8 / 1000,除以1000是因为单位是k
kbps = fs * channels_num * info.BitsPerSample / 8 * 8 / 1000;
fprintf('数码率为%.2f\n',kbps);

双声道图像

李萨如图形

代码二:代码二的bug是数据长度这里,因为不同的文件数据长度在wav文件中不一定是从75开始的4位数据。只是对当前文件适用,暂时没找到确定数据长度位置的方法。

clc;
clear;
close all;

%获得数据长度
filepath = 'speaking.wav';%这里请自己设置路径
fileID = fopen(filepath);
A = fread(fileID);

%声道数
info.channels_num = add_helper(A,23,2);%在第24和23位,24位为高位
fprintf('声道数为%d位\n',info.channels_num);
%采样频率
info.fs = add_helper(A,25,4);%从25位开始,持续4位
fprintf('采样频率为%d位\n',info.fs);
%取样位数
info.bits_per_sample = add_helper(A,35,2);
fprintf('取样位数为%d位\n',info.bits_per_sample);
%数据长度,因为这里有一个数据类型转换两个byte才被视为一个数据值
data_length = add_helper(A,75,4);
[info.data_length,info.data_length_type] = calculate_file_len(data_length);
fprintf('数据长为%.2f %s\n',info.data_length,info.data_length_type);
%文件长
[info.file_length,info.file_length_type] = calculate_file_len(length(A));
fprintf('文件长为%.2f %s\n',info.file_length,info.file_length_type);
%因为是将两字节数据视为1个数据,所以要除以2,因为只取一个声道故需要处理声道数
info.real_length = data_length/info.channels_num/2;
%音频长度
info.music_length = roundn(info.real_length/info.fs,-2);
fprintf('音频文件长度为%.2f s\n',info.music_length);
%与采样位数有关,多少Byte合成一位
val = info.bits_per_sample/8;
%左声道数据
left_wav = zeros(info.real_length/2/val,1);
%右声道数据
right_wav = zeros(info.real_length/2/val,1);

for i = 0:info.real_length-1
    left_wav(i+1) = add_helper(A,79+i*4,2);
    right_wav(i+1) = add_helper(A,79+i*4+val,2);
end

[x,fs] = audioread(filepath,'double');

% figure;
% subplot(2,1,1)
% plot(left_wav);
% subplot(2,1,2)
% plot(right_wav);

Hex_A = dec2hex(A);

% A表示wav文件数据
% start表示起始位
% total表示总位数
% return 得到的十进制数据
function tmp = add_helper(A,start,total)
    tmp = A(start+total-1);
    for i=total-2:-1:0
        tmp = tmp*16*16+A(start+i);
    end
end

% A表示wav文件数据
% return file_length表示文件长度
% return len_type表示长度对应类型,有B,KB,MB,GB
function [len,len_type]=calculate_file_len(native_A)
    len = native_A;
    len_index = 1;
    len_list = {'B','KB','MB','GB'};
    while len >= 1024
        len = len/1024;
        len_index = len_index+1;
    end
    %保留两位小数
    len = roundn(len,-2);
    len_type = len_list{len_index};
end

代码三:
gui格式较为完整。
可以实现的功能如下:
1.数据部分显示音频文件的各项数据。
选择声道
2.其他选项部分可以选择声道显示波形图异或是李萨如图形。
李萨如图形
3.播放选项部分可以跟随动态显示图像。
动态显示1
动态显示2
已上传到我的资源
有不足之处欢迎指出。

  • 41
    点赞
  • 200
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 提取音频的共振峰需要进行一些信号处理的步骤。以下是MATLAB代码示例: ```matlab % 读取音频文件 [y, Fs] = audioread('your_audio_file.wav'); % 设置参数 frameSize = 1024; % 帧大小 hopSize = 512; % 帧移 numCoeffs = 2 + floor(Fs/1000); % LPC系数数量 nfft = 2^nextpow2(frameSize); % FFT点数 % 分帧 numFrames = floor((length(y)-frameSize)/hopSize) + 1; frames = zeros(frameSize, numFrames); for i = 1:numFrames frames(:,i) = y((i-1)*hopSize+1:(i-1)*hopSize+frameSize); end % 计算LPC系数 lpcCoeffs = zeros(numCoeffs, numFrames); for i = 1:numFrames lpcCoeffs(:,i) = lpc(frames(:,i), numCoeffs-1); end % 计算频谱包络 envelope = zeros(nfft/2+1, numFrames); for i = 1:numFrames a = lpcCoeffs(:,i); [h,f] = freqz(1, a, nfft/2+1, Fs); envelope(:,i) = abs(h).^2; end % 寻找共振峰 peaks = zeros(3, numFrames); for i = 1:numFrames [pks, locs] = findpeaks(envelope(:,i), 'SortStr','descend', 'NPeaks',3); peaks(:,i) = f(locs); end % 输出共振峰频率 disp(peaks); ``` 这段代码首先读取音频文件,并进行分帧处理。接着计算每帧的LPC系数,然后通过LPC系数计算每帧的频谱包络。最后,使用MATLAB内置函数`findpeaks`寻找频谱包络中的三个最大峰值,并输出它们的频率。请注意,此代码仅为示例,提取共振峰的结果可能因输入音频的不同而有所变化。 ### 回答2: MATLAB可以通过调用`audioread`函数来读取wav音频文件,并通过调用`resample`函数对音频进行重采样。接下来,我们可以使用MATLAB提供的数字信号处理工具箱中的`resonator`函数来提取共振峰频率。 首先,我们导入音频文件,并将其进行重采样,以确保采样率适合信号处理。假设音频文件的路径为`path_to_wav`,我们可以使用以下代码读取和重采样音频: ```matlab [y, Fs] = audioread(path_to_wav); % 读取音频文件 desiredFs = 44100; % 设定目标重采样率 y_resampled = resample(y, desiredFs, Fs); % 重采样音频 ``` 接下来,我们可以使用`resonator`函数来提取共振峰频率。该函数将音频信号作为输入参数,并返回共振器滤波器的系数和中心频率。我们可以选择使用数字滤波器的类型和阶数来调整共振峰特征的细节。以下是一个简单的示例代码,提取三个共振峰的频率: ```matlab numOfFilters = 3; % 设定共振器数量 order = 10; % 设定滤波器阶数 [R, C] = resonator(y_resampled, numOfFilters, order); % 提取共振峰 resonanceFrequencies = Fs/2 * C/(2*pi); % 计算共振峰频率 ``` 在上述代码中,我们首先使用`resonator`函数提取共振器滤波器的系数和中心频率。然后,通过将中心频率除以2π,并乘以采样率的一半,我们可以计算出共振峰的频率。 最后,`resonanceFrequencies`变量将包含提取的三个共振峰的频率。你可以根据需要对滤波器的类型和阶数进行调整,以获得所需的共振峰特征。 ### 回答3: 基于MATLAB读取wav音频文件提取三个共振峰频率的过程涉及以下几个步骤: 1. 使用MATLAB的audioread函数读取wav文件,并将音频数据保存为一个向量。 2. 对音频数据进行预处理,例如对音频信号进行归一化或者加窗处理。可以使用MATLAB的hamming窗口函数实现加窗。 3. 使用MATLAB的fft函数对加窗后的音频信号进行傅里叶变换,得到频域的信号。 4. 根据傅里叶变换的结果,通过寻找音频信号中的共振峰频率。可以使用MATLAB的findpeaks函数来寻找峰值。 5. 根据峰值的个数,选择其中三个最大的峰值作为共振峰频率。 6. 使用MATLAB的plot函数将频率和幅度值绘制成图形,便于可视化。 以下是一个简单的MATLAB代码示例: ```matlab % Step 1: 读取wav文件 [x, fs] = audioread('audio.wav'); % Step 2: 加窗处理 window = hamming(length(x)); x = x .* window; % Step 3: 进行FFT,得到频域信号 X = fft(x); % Step 4: 寻找峰值 [pks,locs] = findpeaks(abs(X)); % Step 5: 选择三个最大的峰值作为共振峰频率 [~, index] = sort(pks, 'descend'); resonancefreq = sort(locs(index(1:3))); % Step 6: 绘制频率和幅度图 frequencies = resonancefreq * fs / length(x); figure; plot(frequencies, pks(index(1:3))); xlabel('Frequency (Hz)'); ylabel('Amplitude'); title('Resonance Frequencies'); ``` 通过上述步骤,我们可以基于MATLAB读取wav音频文件提取三个共振峰频率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值