I am processing a real audio data which consists of three different signals of the same frequency. Those three signals are consisted of 7 beeps and are different in length and energy level. (For every signal, the delay between each beep is different)
Signal 1:
Signal 2:
Signal 3
My goal is to filter out every of these signal using the respective matched filter. But the problem is the strength of the signal 1 is too high and I can not apply the other signals matched filter for the data (because the signal 1 will mask the filtering results of other matched filter).
I try to put the process in a loop. After each loop, the filtered signal will be subtracted from the data. But in many cases, the beeps from one signal will be aligned with the beeps of other ones (as in the second picture: the final beep of signal 2 is masked by the stronger beep of another signal).
My questions are:
How can I correctly subtract the stronger signals without affecting the weaker ones?
After matched filtering, I only got the energy of the signal and matching position. Is there any way to determine the peaks of the beeps from this energy?
Edit:
This is my code to extract the strongest signal:
t_matched = 165428; %matching position
ct3133 = signal_generator(ones(250,1), fs/25, 380, 640, 460, 640, 400, 640); %generate the "signal 1"
n = length(ct3133);
signal_size = length(A222203_30s_d);
t_begin = t_matched - 3.16*fs/25 -125-5; %position where the signal 1 begin to transmitted
% 3.16(s) = (380 + 640 + 460 + 640 + 400 + 640)(ms)
% 25: decimation factor
% 125: the length of 1 beep (10ms)
% 5: correction coeffecient due to the dealy between each beep is not ideal.
%Extracting the signal 1
signal = cat(1, zeros(t_begin, 1), abs(ct3133), zeros(signal_size - t_begin - n, 1));
ct3133_sup = abs(ones(length(signal),1)-signal);
ct3133_extracted = A222203_30s_d.*ct3133_sup;
With this method, I was able to remove the Signal 1 from the input data. However, this also removed the last beep of the signal 2 which is masked by the fifth beep of the signal 1.
With the last beep of the signal 2 gone, the signal 2 can be detected by a corresponded matched filter but the matching position is not correct. Therefore, the future operation of removing the signal 2 can not be performed.
Edit 2:
Here is some graph and data after the extracting of signal 1 operation.
Signal 1 peak and location values:
0.0413 & 125804
0.0411 & 130555
0.0410 & 138555
0.0415 & 144305
0.0417 & 152305
0.0413 & 157306
0.0415 & 165306
Matched filtering result of signal 1 (X: matched position, Y: Signal 1 Energy):
X = 165427, Y = 21.32.
Input data after signal 1 is removed:
Clearly, the signal 2 only contains 6 beeps where it supposes to be 7.
Signal 2 peaks values and locations, respectively:
Peak 1: 0.00102 & 110460
Peak 2: 0.001114 & 115211
Peak 3: 0.001097 & 123211
Peak 4: 0.001141 & 128961
Peak 5: 0.001139 & 136711
Peak 6: 0.001119 & 145462
Result after filtering the above data with the matched filter of signal 2:
The peak value and location are : 0.3615 & 152383
*The location is the samples, data sampling rate : 12500Hz
Related
I got a TF of my plant G(s) = s + 10/3s^3 + 8s^2 + 30s + 25 and I would like to implement a PID controller so that the system closely follows the varying input signal, I used r(t) = 0.5sin(t) + 0.5. How can I calculate the correct setting for Kp, Ki and Kd to do this without guessing random values?
I made this feedbackloop in simulink
And I want an output signal that follows the input signal, so the yellow and blue line should lie on eachother.
folks. I have been working on an application with MFCC for voice recognition. At first, having recorded my voice signal (with 24000 samples), it goes through this high pass filter:
for n=2:length(x)
y(n) = x(n) - 0.95*x(n-1);
end
After that, I must resample this signal with a period of 20ms, meaning that I should eliminate the unused samples and retrieve the ones with index 160, 320, 480 and so on. Thus, I have used the following piece of code:
for n=1:length(y)
if (rem(n,160)) == 0
y(n) = y(n);
else
y(n) = [];
end
end
However, I did not have any success with this last part (MATLAB says Matrix index is out of range for deletion). What should I do?
The problem of the code is you remove the elements of y inside the loop and loop on the length of the old y.
You can do the whole of the second part using the following code:
y = y(160:160:length(y));
This code get the all index of y which are dividable by 160.
However, you should be aware of changing the size of the y after this operation.
Kindly tell me the theory behind the two commands (marked with ***) of an AWGN channel in the below shown code.
Code:
N_all = [10^3*ones(1,6) 10^3*ones(1,5)];
Eb_no = [0:2:20];
for ii=1:length(Eb_no)
N = N_all(ii);
b = (1/sqrt(2))*rand(1,N)>0.5;
ip = qpsk_new(b);
s = ip;
*** noise = 1/sqrt(2) * [randn(1,N/2)+j*randn(1,N/2)];
*** y = s+10^(-Eb_no(ii)/20)*noise;
end
The randn function in the first marked line generates complex, Gaussian-distributed (1), independent (2) samples with zero mean and unit variance. The second marked line scales those samples according to the specified signal-to-noise ratio (EB/N0) and adds (3) them to the signal.
These operations stem from the definition of AWGN:
The "G" in "AWGN" means "Gaussian".
The "W" means "white". The term "white" applied to a stochastic process means that the samples are statistically independent (or uncorrelated; but in the Gaussian case they are equivalent conditions).
The "A" is "additive", so you add the noise to the signal.
I need to get 3 input audio stream to matlab simultaneously using 3 USB mics and find out the highest amplitude in real time.
this is the mics initialization
mic1= dsp.AudioRecorder('DeviceName','ÇáãíßÑæÝæä (10- USB PnP Sound Device)', 'SampleRate', 48000, 'NumChannels', 1);
mic2= dsp.AudioRecorder('DeviceName','ÇáãíßÑæÝæä (9- USB PnP Sound Device)', 'SampleRate', 48000, 'NumChannels', 1);
mic3= dsp.AudioRecorder('DeviceName','ÇáãíßÑæÝæä (8- USB PnP Sound Device)', 'SampleRate', 48000, 'NumChannels', 1);
frame1=step(mic1);
frame2=step(mic2);
frame3=step(mic3);
what are the next steps?
By examining your code, you have three audio signals with one channel each. If I understand what you want correctly, you want to find the highest sound made by any one signal overall over time. However, if I understand you correctly, you can't do this in real time as step for the AudioWriter can only capture one frame at a time. Because you're specifically trying to capture from all three audio devices, and the only way for you to capture audio is with step, you'll have to serially call step for each signal that you have.
Therefore, you'll need to capture all three audio signals separately, and then do your analysis. You'll also want to clip the sound after a certain point, so perhaps something like 5 seconds. Therefore, you'd do something like:
time_end = 5;
%// Capture audio signal 1
tic;
frame1 = [];
while toc < time_end
audio_in = step(mic1);
frame1 = [frame1; audio_in(:)];
end
%// Capture audio signal 2
tic;
frame2 = [];
while toc < time_end
audio_in = step(mic2);
frame2 = [frame2; audio_in(:)];
end
%// Capture audio signal 3
tic;
frame3 = [];
while toc < time_end
audio_in = step(mic3);
frame3 = [frame3; audio_in(:)];
end
After this point, because the sounds will probably all be uneven length, you'll want to zero pad all of them so they all match the same length. After this, it's a matter of first finding the maximum amplitude for each sample for all three signals, and then finding the maximum out of all of this.
I'm not quite sure how the signals are shaped... if they are row or column vectors, so let's just make sure they're all column vectors. Then, use max and operate along the columns and find the maximum for each point in time, then find the maximum out of all of these.
Therefore:
%// Find lengths for all three signals
l1 = numel(frame1);
l2 = numel(frame2);
l3 = numel(frame3);
max_length = max([l1, l2, l3]);
%// Zero pad signals to make same length
frame1_pad = zeros(max_length,1);
frame2_pad = zeros(max_length,1);
frame2_pad = zeros(max_length,1);
frame1_pad(1:l1) = frame1;
frame2_pad(1:l2) = frame2;
frame3_pad(1:l3) = frame3;
%// Find maximum among each sample
max_signal = max([frame1_pad, frame2_pad, frame3_pad], [], 1);
%// Find the maximum amplitude overall and location
[max_amplitude, loc] = max(max_signal);
max_amplitude will contain the highest point overall at a particular time point for each of the three signals, and loc will tell you the location in the array of where it was found. If you want to find the actual time it occured, simply take loc and multiply by your sampling time (1/48000). Bear in mind that loc will be 1-indexed instead of 0-indexed, and so you need to subtract by 1 before multiplying by the sampling rate.
Therefore:
time_it_happened = (loc-1)*(1/48000);
time_it_happened will contain that time which the highest amplitude happened.
Good luck!
From an audio stream vector in Matlab I am trying to identify the time of onset and finish of audible events that occur multiple times within the time series data.
I am very much a novice with Matlab, but I have written code which identifies the peak and location of the event, however, I need to get the start of the event relative to a user defined threshold which occurs several tens of milliseconds before the peak.
Here is the code I am using at the moment:
function [emg] = calcPeaks(EMG, thresh)
%Rectify and downsample data
emg = resample(abs(hilbert(EMG)),1000,10000);
%Low Pass Filter
[b,a]=butter(8,0.01,'low');
emg=filtfilt(b,a,emg);
%Plot the processed vector
plot (emg); hold on;
%Find maximum for each Peak and Location
[pks,locs] = findpeaks(emg(1:end-2000),'minpeakheight',thresh);
plot(locs, emg(locs), 'ko'); hold on;
%Find Crossings above threshold
[FindCross] = find(emg(1:end-2000) > thresh);
[Gaps] = find(diff(FindCross)> thresh);
plot(FindCross, emg(FindCross), 'ro');
plot(Gaps, emg(Gaps), 'bo');
I tried to post an image of the datat but I don't have enough reputation :(
This should be getting you close to what you want (although same thresh for both is probably not what you intend):
[FindCross] = find(emg(1:end-2000) > thresh); %thresh is your minimum volume
[Gaps] = find(diff(FindCross)> thresh2); % thresh2 is related to the timing of events
However, note that this only finds gaps between areas which are above your noise level threshold, so won't locate the first event (presuming at start of data you are below the threshold).
A simple way to do this sort of thing is to threshold and then use diff to look for rising and falling edges in the thresholded data.
emg2 = emg > thresh; %emg2 = 1 and 0 for event / non event
demg = diff(emg2); % contains 0, -1, 1
rise = find(demg>0)+1; %+1 because of how diff works
fall = find(demg<0);
rise should then contain the positions where emg goes from below threshold to above threshold. If the data is sufficiently noisy, this could contain false positives, so you may want to then filter those results with additional criteria - e.g. check that after the rise the data stays above threshold for some minimum period.
The problem with doing it by the method you're using to find gaps is the following. Presume your data looks like this, where 0 is below threshold and 1 above threshold: 000111000111000. That is, our first event starts at index 4 and finishes at index 6, and the second starts at index 10 and ends at index 12.
emgT = find(emg > thresh);
This finds all the places where our data = 1, so emgT = [4,5,6,10,11,12]
emgD = diff(emgT);
This takes the difference between emgT(n+1), and emgT(n) - since there's no n+1 for the final datapoint, the output is one smaller than emgT. Our output is [1 1 4 1 1] - that is, it will find the gap between the two events, but not the gap between the start of the file and the first event, or the gap between the last event and the end of the file.