I want to implement an end point detection for a tall spike in a sound signal
2 views (last 30 days)
Show older comments
Hello, I need help extracting the two indices of marked with two red crosses on the figure below. I need those two indices to extract the first tall wave of the signal outlined in red. The two red crosses are points that intersect with zero, but I can't use find(y == 0) since there is no point exactly at 0.
I need to extract these two points since they make up one period of the tall signal. I have multiple signals like this, but all with different peak locations and amplitudes. However, all the other signals also have the tallest wave as the first signal.
So far, I've tried this method:
[~, loc] = findpeaks(signal, 'MinPeakHeight', 0.2); % Get index of max amplitude above 0.2 (this threshold is arbitrary).
firstpeak = loc(1);
signal_inverse = -signal; % Inverse the signal.
[~, loc] = findpeaks(signal, 'MinPeakHeight', 0.2); % Get index of max amplitude of the inverted signal.
secondpeak = loc(1);
pad = (secondpeak - firstpeak) / 2; % Get a quarter of the wave's period.
signal = signal(firstpeak-pad:secondpeak+pad); % Subtract pad from first peak and add pad to second peak.
This, however, assumes that all waves are perfect and don't catch any noise.
A new and better approach I'm thinking of is using the Zero-Crossing detection algorithm. I've already seen many on MATLAB community, but I don't seem to be applying those into my signals properly.
Any help would be appreciated. Thank you!!
3 Comments
Adam Danz
on 22 Sep 2020
With these kinds of problems you need to define a set of rules before getting into algorithms and those rules should apply to all possible circumstances.
Judging from the singel example in the image, one set of rules may be,
- The segment starts the first time the signal passes 0.1% of the signal's height in the positive direction, where the height is defined by the range of y values in your signal.
- The segment ends at the first element greater than y=0 after the signal passes into negative y values.
- The length of the signal must be greater than 20 samples. If it's less than 20 samples, the segmented part is ignored and the algorithm starts again after the false end-point.
Write down these rules in plain language before developing the algorithm. It's likely that the rules will need changed in the process which is a sign that you're getting closer to the ideal set of rules needed to solve your problem.
Accepted Answer
Adam Danz
on 24 Sep 2020
Edited: Adam Danz
on 24 Sep 2020
"only one should be the true "tall" peak (the first peak read in the data)"
Are you sure about that? That's this peak in the data you shared. I like your other defintion better, "the first peak of the original data that exceeds this threshold value is considered the positive peak".
I have a proposal.
- Find the main peak using the rule you already defined. That will give you point "A" in the image below.
- Assuming the baseline signal is centered at y=0, points 1, 2, and 3 in the image below are the first 0-crossing before A, the first 0-crossing after A, and second 0-crossing after A. What you need, if I understand correctly, are points #1 and #3.
0-crossings can be approximated with,
zeroCrossIdx = [false; diff(sign(x))~=0];
hold on
plot(find(zeroCrossIdx)-.5, 0, 'mo', 'MarkerSize', 4)
Although there are more precise methods (ie, interpolation, also see file exchange for intersection points).
If the baseline signal is not centered at y=0 you could center it by averaging the signal prior to the first peak or removing the peaks and then avg'ing the signal, and then shift vertically based on the avg.
2 Comments
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!