Проблема
Мне было поручено разработать аудио-визуализатор с использованием FFT в matlab.Я прошел через большую часть того, что я хочу сделать с аудио-визуализатором, но у меня возникли проблемы с плавным запуском программы, потому что мой процессор ее душит.Я хочу сделать больше с моим визуализатором, но я не хочу больше реализовывать функции, прежде чем я смогу заставить основы работать хорошо.
Фон
Программадействительно две части.Первая часть представляет собой аудиоплеер и запускает скрипт matlab, который называется CLICK_ME.m
.Второй - currentfft()
.Он берет информацию из песни, и прежде чем я ее обработал, он нанёс на график (частоту, мощность).Однако это самый простой визуализатор, и мой профессор хочет, чтобы мы создали уникальный аудио-визуализатор.
Моя идея состояла в том, чтобы построить график одного из тех пятиугольников статов, где радиус каждой из пяти точек - это мощность, отфильтрованная между пятью полосами частот.
Естественно, я реализовал функцию bandpass()
в Matlab.и это делает то, для чего он предназначен.Однако он требует гораздо большей вычислительной мощности, чем я мог ожидать, и впоследствии он оказывается узким местом и выглядит действительно нестабильным.
Я попытался уменьшить количество точек, по которым он должен выполнять вычисления, используя цикл for дляпринимать каждое другое или каждое третье значение.Я сделал это до сокращения в десять раз без какого-либо заметного успеха.Если я уберу больше, чем каждый десятый пункт, я получаю ошибки от Matlab, что он не может выполнить bandpass()
менее чем на шести выборках.
Мой профессор предложил принять gaussmf()
или rectangularPulse()
дляимитировать что-то близкое к полосовому фильтру, но я не уверен, как их реализовать или будет ли он еще быстрее.
function currentfft ( player, Y, FS )
sampleNumber = get( player, 'CurrentSample' );
timerVal = get( player, 'TimerPeriod' );
%Get channel one values for our window around the current sample number
s1 = Y(floor(sampleNumber-((timerVal*FS)/2)):floor(sampleNumber+((timerVal*FS)/2)),1);
n = length(s1);
p = fft(s1); % take the fourier transform
nUniquePts = ceil((n+1)/2);
p = p(1:nUniquePts); % select just the first half since the second half
% is a mirror image of the first
p = abs(p); % take the absolute value, or the magnitude
p = p/n; % scale by the number of points so that
% the magnitude does not depend on the length
% of the signal or on its sampling frequency
p = p.^2; % square it to get the power
% multiply by two
if rem(n, 2) % odd nfft excludes Nyquist point
p(2:end) = p(2:end)*2;
else
p(2:end -1) = p(2:end -1)*2;
end
% reduce the number of points actually being filtered
q = 1;
s = 1;
d = int16( length(p) );
pNew = zeros( [ d/10, 1 ] );
while q < d
pNew(s) = p(q);
q = q + 10;
s = s + 1;
end
% try gaussian or rect functions instead of bandpass?
% radius of each section of the pentagon
p0 = abs( bandpass(pNew, [ 1 60 ], FS) );
p1 = abs( bandpass(pNew, [ 60 250 ], FS) );
p2 = abs( bandpass(pNew, [ 250 2e3 ], FS) );
p3 = abs( bandpass(pNew, [ 2e3 8e3 ], FS) );
p4 = abs( bandpass(pNew, [ 8e3 20e3 ], FS) );
% length( p0 )
% length( p1 )
% length( p2 )
% length( p3 )
% length( p4 )
pArr = [ p0, p1, p2, p3, p4 ];
%freqArray = (0:nUniquePts-1) * (FS / n); % create the frequency array
thetaArr = [ pi/2, 4.5*pi/5, 6.5*pi/5, 8.5*pi/5, 10.5*pi/5 ];
% calculating x and y from the radii
x = cos(thetaArr) ./ pArr;
y = sin(thetaArr) ./ pArr;
plot(x, y)
xlabel('Frequency (Hz)')
ylabel('Power (watts)')
title('Frequency vs. Power')
grid on;
axis([-20e9 20e9 -20e9 20e9]);
Я бы хотел, чтобы этот код работал гладко, не пропуская мой процессор через отжиматель,Это, однако, не работает гладко и максимизирует два потока на моем компьютере.