- audioOscillator to create a frequency-varying sine wave signal
- pitch to estimate the pitch of a signal
- timescope to visualize the original and reconstructed signals.
Recreating Sine Wave from pitch detection
5 次查看(过去 30 天)
显示 更早的评论
Dear Community, I am looking for a way to rebuild a signal from the pitch information from an other signal. Best scenario would be to read in a sine wave with changing pitch, extract the pitch information and then to be able to apply it to a sine wave. Any help is very much appreciated! Thanks!
0 个评论
采纳的回答
jibrahim
2022-8-29
Hi Hans,
Here is some code that approximates what you want. It uses:
% Create the original frequency-varying sine wave signal
src = audioOscillator;
F = [100:500 499:-1:100];
% We will change the frequency every 10 frames
numFramesPerFreq = 10;
frameLength = src.SamplesPerFrame;
sig = zeros(numFramesPerFreq*size(F,2)*frameLength,1);
% Build the sine wave
for index=1:size(F,2)
src.Frequency = F(index);
for index2=1:numFramesPerFreq
startInd = (index-1)*numFramesPerFreq*frameLength+(index2-1)*frameLength + 1;
sig(startInd:startInd+frameLength-1) = src();
end
end
% Estimate the pitch of the signal
% A pitch estimate is generated for every "hop" of samples
p = pitch(sig,src.SampleRate,WindowLength=1024,OverlapLength=896);
% Hop length is window length - overlap length
hopLength = 1024-896;
% This is the reconstructed signal (based on pitch estimates)
sig2 = zeros(hopLength*size(p,1),1);
% We will build this signal
src = audioOscillator;
frameLength = hopLength;
src.SamplesPerFrame = hopLength;
for index=1:size(p,1)
% For every frame, use estimated pitch
osc.Frequency = p(index);
sig2((index-1)*frameLength+1:index*frameLength) = src();
end
% Make original and reconstructed signals the same length
L = min(size(sig,1),size(sig2,1));
sig = sig(1:L);
sig2 = sig2(1:L);
% Use a scope to visualize the signals
scope = timescope(SampleRate=src.SampleRate,...
LayoutDimensions=[2 1],...
NumInputPorts=2,...
TimeSpan=.1,...
YLimits=[-1 1]);
scope.ActiveDisplay = 2;
scope.YLimits = [-1 1];
numFrames = size(sig,1)/hopLength;
for index=1:numFrames
in1 = sig((index-1)*hopLength+1:index*hopLength);
in2 = sig((index-1)*hopLength+1:index*hopLength);
scope(in1,in2)
end
6 个评论
jibrahim
2022-9-2
A little more info. For pure tones, you should use instfreq. All of the pitch algorithms are exploiting the harmonic structure of voice--they're really not designed for pure tones, and simpler algorithms like instfreq will perform best:
A = 1;
fs = 44100;
dt = 1/fs;
t = 0:dt:10;
f1 = 1000;
x = A*sin(2*pi*f1*t);
y = A*sin(2*pi*f1*t);
filename = sprintf('%d.wav',f1);
stereo_mtx = [x(:), y(:)];
instfreq(stereo_mtx,fs);
More info on the pitch function: It has a range parameter which is set by default to handle speech signal (default range is [50, 400] Hz). You can adjust the range for your case:
A = 1;
fs = 44100;
dt = 1/fs;
t = 0:dt:10;
f1 = 1000;
x = A*sin(2*pi*f1*t);
y = A*sin(2*pi*f1*t);
filename = sprintf('%d.wav',f1);
stereo_mtx = [x(:), y(:)];
pitch(stereo_mtx,fs,Range=[50 5000]);
The function pitchnn should work for both types of sound (speech and sine waves are fine)
更多回答(1 个)
Image Analyst
2022-8-29
Attached is a demo that creates a sound. Perhaps you can adapt it to change the frequency and amplitude envelope to whatever you want.
0 个评论
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!