首页 > 解决方案 > 使用 Matlab 进行 PCA 声音压缩

问题描述

我正在尝试使用 PCA(主成分分析)构建声音压缩器。

输入声音始终是单声道声音,因此生成的矩阵是sampledData代码中调用的列矩阵。

压缩声音需要将矩阵转换为 2D 矩阵。因此,需要按以下方式对样本进行分组:

这里分组大小为 3,声音由 7 个样本组成

[sample1   sample2   sample3
 sample4   sample5   sample6
 sample7      0         0   ]

分组大小较低(=矩阵所需的列数)例如 10 或较高的分组大小(例如 100 或更多)会发生什么变化?

[sampledData, sampleRate] = audioread("soundFile.wav");

data = sampledData;
groupingSize = 10;  %Number of columns wanted from the data

%Make data size a multiple of groupingSize and fill with 0
data(end + 1:groupingSize*ceil(numel(data)/groupingSize))=0;

%Make data a matrix of x rows and groupingSize columns
data = transpose(reshape(data,groupingSize,[]));

这是我用于声音压缩的剩余代码。percentagePC不幸的是,当小于 100时出现错误,表示compressed矩阵的列数需要与 的倒数的行数具有相同的列数eigenVec

为了说明,我使用groupingSize = 100which 给我一个 100 列的压缩矩阵,它eigenVec是一个 100 行和 100 列的矩阵。如果我设置percentagePC = 90然后得到一个 90 列的压缩矩阵(我保留 90% 的最有用的数据),所以为了能够将两个矩阵相乘,我理论上需要将矩阵的大小减少eigenVec10 列。根据 PCA,这是正确的推理吗?

percentagePC = 90;  %Percentage of principal component to keep

[rows, cols] = size(data);

%get eigenvalues and eigenvector by centering data matrix and getting its covariance
dataCR =(data-ones(size(data,1),1)*mean(data))./(ones(size(data,1),1)*std(data,1));
dataCov = cov(dataCR);
[eigenVec, eigenVal] = eig(dataCov);

%Sort eigenvectors (desc)
[~, index] = sort(diag(eigenVal), 'descend');
eigenVec = eigenVec(:, index);

%principal components calculation
P = zeros(rows,cols);
for i = 1:cols
    P(:,i) = dataCR * eigenVec(:,i);
end

%Number of principal components wanted according to percentagePC
iterations = ceil((groupingSize*percentagePC)/100);

compressed = zeros(rows,iterations);
for i = 1: iterations
    compressed (:,i) = P(:,i);
end

%Fuse principal components between each other to get final compressed signal
final_compressed = zeros(rows*iterations,1);
z=1;
z = 1;
for i = 1:iterations:rows*iterations
    for j = 1:iterations
        final_compressed(i+j-1,1) = P(z,j);
    end
    z = z + 1;
end

% Decompression of compressed signal
decompressed = compressed * (eigenVec^(-1)); % /!\ ERROR IS HERE /!\
[rowsD,colsD] = size(decompressed);

final_decompressed = zeros(rowsD*colsD,1);
z = 1;
for i = 1:colsD:rowsD*colsD
    for j = 1:colsD
        final_decompressed(i+j-1,1) = decompressed(z,j);
     end
     z = z + 1;
end


filenameC = fullfile('compress.wav');
filenameD = fullfile('decompress.wav');

audiowrite(filenameC, final_compressed/max(abs(final_compressed)), round(sampleRate/(groupingSize/iterations)));
audiowrite(filenameD, decompressed, sampleRate);

标签: matlabpca

解决方案


推荐阅读