Generate pinknoise with same power as audio

11 ビュー (過去 30 日間)
L
L 2023 年 8 月 25 日
回答済み: Mathieu NOE 2023 年 8 月 28 日
I need to read an audio file and generate a pinknoise with the same power.
I tought using generatepinknoise(), but the built-in function does not accept a power specification.
Any ideas?
I was trying something based on https://stackoverflow.com/questions/17795675/making-pink-noise-1-f-using-list-of-frequencies, but it dosen't sound anything like pinknoise.
% Generate pinknoise with same power as sound
% get sound (2 channels)
[y,Fs] = audioread('S5.wav');
Y=fft(y);
A1 = abs(Y(:,1)); P1 = mean(A1.^2);
A2 = abs(Y(:,2)); P2 = mean(A2.^2);
N = length(Y); invfnorm = 1./[1:N]';
Anew1 = sqrt(P(:,1)*invfnorm/sum(invfnorm)); Anew2 = sqrt(P(:,2)*invfnorm/sum(invfnorm));
noise = ifft([Anew1 .* exp(1i*angle(Y(:,1))) Anew1 .* exp(1i*angle(Y(:,1))) ] ,'symmetric');
soundsc(noise,Fs)

採用された回答

Mathieu NOE
Mathieu NOE 2023 年 8 月 28 日
hello
this would be my suggestion . You don't need to do a fft to get the power of a signal (you can compute it directly in time domain too)
here I tested it on my own audio signal (piano.wav)
% Generate pinknoise with same power as sound
% get sound (2 channels)
[y,Fs] = audioread('S5.wav'); % your file
% [y,Fs] = audioread('piano.wav'); % mine
[samples,channels] = size(y);
y_power = mean(y.^2,1); % power of signals
pn = mypinknoise(samples);
pn_power = mean(pn.^2); % yes it's 1 because normalized std as explained in the subfunction
% let's assume we want same pink noise power as audio channel of largest
% power
pow_factor = max(y_power)/pn_power;
% now the pink noise signal must be multiplied by the square root of the
% power factor
pn = pn*sqrt(pow_factor);
pn_power = mean(pn.^2); % double check ; now we have same noise power as the audio signal
% concatenate signals for replay
out = [y; pn(:)*ones(1,channels)];
soundsc(out,Fs);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = mypinknoise(N)
% function: y = pinknoise(N)
% N - number of samples to be returned in a row vector
% y - a row vector of pink (flicker) noise samples
% The function generates a sequence of pink (flicker) noise samples.
% In terms of power at a constant bandwidth, pink noise falls off at 3 dB/oct, i.e. 10 dB/dec.
% difine the length of the vector and
% ensure that the M is even, this will simplify the processing
if rem(N, 2)
M = N+1;
else
M = N;
end
% generate white noise
x = randn(1, M);
% FFT
X = fft(x);
% prepare a vector with frequency indexes
NumUniquePts = M/2 + 1; % number of the unique fft points
n = 1:NumUniquePts; % vector with frequency indexes
% manipulate the left half of the spectrum so the PSD
% is proportional to the frequency by a factor of 1/f,
% i.e. the amplitudes are proportional to 1/sqrt(f)
X = X(1:NumUniquePts);
X = X./sqrt(n);
% prepare the right half of the spectrum - a conjugate copy of the left one,
% except the DC component and the Nyquist component - they are unique
% and reconstruct the whole spectrum
X = [X conj(X(end-1:-1:2))];
% IFFT
y = real(ifft(X));
% ensure that the length of y is N
y = y(1, 1:N);
% ensure unity standard deviation and zero mean value
y = y - mean(y);
y = y/std(y, 1);
end

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangePulsed Waveforms についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by