Detecting first non silent sample index - puredata

I have an audio file that I read with [tabread~]). The audio starts with some silence and I am trying to find the first non silent sample index.
I have tried to use [bonk~], [fiddle~] or [sigmund~] but the results were approximate and not constants.
Does anyone have a solution for this? Thanks.
Pascal

I already answered this question in the Pure Data forum, but I am copying it here (slightly adapted) in case someone else find it useful:
If the sound completely silent up to the point you marked (that is, is the table filled with zeroes up to that point) then you can simply go through the array's elements using [tabread ], starting at the first sample and checking if the absolute value of the subsequent ones is larger than zero. If the signal is not completely silent but near silent, then you will can either use sort of attack detection (such as [bonk~]) or simply use something like this:
...
|
[tabread array1]
|
{abs]
|
[> 0.001]
|
[sel 1]
|
...
Note how I used [> 0.001] instead of [> 0]. Adjust this number (either directly as an argument or via the rightmost inlet of [>]) to control the sensitivity of the detection. Then once [sel 1] receives a float of value 1, you can use its bang to stop the process since you found your first non-silent element.

Related

define a 4th rank tensor in Maple

I am a newbie in Maple. Could you please help me to convert the following short code from Matlab to Maple:
I=0.0;
for i1=1:3
I(i1,i1,i1,i1)=1.0;
end
I've tried to write it like:
unprotect(I);
I:=0.0;
for i1 from 1 to 3 do
for i2 from 1 to 3 do
for i3 from 1 to 3 do
for i4 from 1 to 3 do
if i1=i2 and i2=i3 and i3=i4 then I[i1,i2,i3,i4]:=1.0;
else I[i1,i2,i3,i4]:=0.0;
end if;
od;
od;
od;
od;
But it gives the following error:
Error, illegal use of an object as a name
Error, illegal use of an object as a name
Can anybody tell me what's wrong?
Thank you,
It'd be easier if you didn't insist on using the name I, which in Maple has the special meaning of the sqrt of -1.
restart;
interface(imaginaryunit=j):
local I:=Array((1..3)$4,datatype=float[8]);
for i1 from 1 to 3 do
I[i1,i1,i1,i1]:=1.0;
end do:
The above produces I as a 4-dimensional Array, where each dimension has a width of three elements. And the three "long diagonal" elements are all initialized to 1.0. And the Array can contain hardware double precision floats. And all the other elements are 0.0 by default.
Is that what you were trying to do?
If you don't insist on calling assigning it to the special name I then things are easier. Eg,
restart;
II:=Array((1..3)$4,datatype=float[8]):
for i1 from 1 to 3 do
II[i1,i1,i1,i1]:=1.0;
end do:
You cannot properly override/disable the special meaning of I merely by unprotecting it. (And even if you could, unprotecting and redefining I is an unworkable idea since a significant portion of Maple commands would then no longer compute properly in the given session.)
Recent versions of Maple allows you to create a so-called top-level "local" instance of that name, which can be used separately from the usual global name I. If you insist on that route, and if your Maple version is recent enough to support that, then you'd probably also want to change the
interface setting for the imaginary unit (sqrt of -1) so that things don't get too confusing. That's why I showed it in the first example above.
But I really think that you'd find things easiest if you just used another name, like II or what have you.
You don't need to put the datatype=float[8] restriction on the Array. But if your subsequent code mimics some (originally) Matlab code then maybe floats are all that will be assigned into the Array. And some operations on Arrays can be much faster, with it. See how it goes.

Matlab not taking last number in array?

I've got a Subscripted assignment dimension mismatch problem.
I've already localized the issue, and know exactly what is going on, I just don't know why.
Here's the problematic piece of code:
mFrames(:,i) = vSignal(round(start:1:frameLength*samplingRate));
start=start+frameShift*samplingRate;
frameLength = frameLength+frameShift;
I've already checked what's going on in debugmode; usually my resulting column length of mFrames is 128, this stays the same until i=1004. Then, my column length changes to 127.
I've checked the values involved while in debug mode, and it simply does not make sense what is going on. At i==1004 start=32097 and frameLength*samplingRate=32224.
That's a difference of 127 meaning 128 points, that should work.
BUT when i assign a vector A=round(start:1:frameLength*samplingRate)
OR B=start:1:frameLength*samplingRate
In both cases I get a vector going from 32097 to 32223. This ALTHOUGH when I give in frameLength*samplingRate matlab is giving me 32224.
In other words, matlab is telling me it's using one number, but when I test I find it's using a different one.
Any help appreciated.
I suspect your 32224 is not actually 32224. MATLAB's default format only displays so many decimal places, so when dealing with floating point numbers, what is printed on screen is not necessarily the "exact" value.
Let's go back a step and look at how the synatx x = start:step:end works.
1:1:10 should give us numbers in steps of 1 from 1 to 10. Fair enough, that makes sense. What if we set the end value to something that's slightly above 10?
e.g.:
1:1:10.1
Well, it still gives us 1:1:10, (or 1:10, 1 being the default step) because we can't have values higher than the end-point, so 11 isn't a correct step.
So what about this:
1:1:9.99
Spoiler: it's the same as 1:9
And this?
1:1:9.9999999
Yep, still 1:9
But if we do this:
a = 9.9999999;
Then with default format, the value of a will be shown on the command line and in your list of workspace variables as 10.0000.
Now, if frameLength and samplingRate are both stored as floating point numbers, it's possible that the number you see as 32224 is not 32224 but very slightly below that. You can check this by changing your default format - e.g. format long at the command line - to show more decimal places.
The simplest solution is probably to do something like:
B=start:1:round(frameLength*samplingRate)
Or try to store the relevant values as integers (e.g., uint32).

image processing using template matching approach

i am working on a project related to template matching image processing , i have done the matching algorithm but the problem i am facing that , template matcher always yeilds the best co-relation matched in source image of template image but i want to notify or respond only when the desired output comes neither on false output. i want to serially communicate MATLAB code with arduino board UNO R3 which will generate the pulse birectionaly when the output comes ? so what should i supposed to do ?
this is the code :
cam=videoinput('winvideo',2,'YUY2_320x240');
start(cam);
preview(cam);
set(cam,'ReturnedColorSpace','RGB');
get=input('get frame ???');
frame=getsnapshot(cam);
imwrite(frame,'got.jpg');
I=imread('D:\Template matcher\got.jpg');
H_Eq=vision.HistogramEqualizer;
Temlate_matcher=vision.TemplateMatcher;
Temlate_matcher.Metric='Maximum absolute difference';
Temlate_matcher.OutputValue='Metric matrix';
marker_inserter=vision.MarkerInserter('Size',30,'Fill',false,'FillColor','White','Opacity',0.75);
I=rgb2gray(I);
I=step(H_Eq,I);
Template1=imread('D:\Template matcher\ge.jpg');
Template1=rgb2gray(Template1);
H_Eq=vision.HistogramEqualizer;
Template1=step(H_Eq,Template1);
Location1=step(Temlate_matcher,I,Template1);
marker_inserter.Shape='Square'
output_image=step(marker_inserter,I,Location1);
figure();imshow(output_image);
As we have discussed in our comments, template matching using the Computer Vision toolbox will produce the best template match in the frame. However, this does not necessarily mean that the object you are searching for is located within the location of where the template best matched.
As such, what I would recommend you do is take a look at what the metric gives you for that template. In your case, you're using the maximum absolute difference. If this metric is less than some threshold, then that could mean that the template was found in the frame you are examining. If it's greater, then there is a good possibility that it wasn't. This threshold you'll have to play around with as it totally dependent on what the template looks like and the contents of the frame you're trying to look at. If it is less than some threshold, then you can send your signal to the Arduino board. Before we do this, you must change your Template Matcher setup so it looks like this:
Temlate_matcher=vision.TemplateMatcher('OutputValue', ...
'Best match location', 'BestMatchNeighborhoodOutputPort', true);
This will allow us to get what we eventually want. As such, you can't use Metric Matrix as the OutputValue field anymore so get rid of this line in your code. Now that this is set up, you can override the behaviour of the template matching by replacing this code:
Location1=step(Temlate_matcher,I,Template1);
With this:
[Location1, NVALS, NVALID] = step(Temlate_matcher,I,Template1);
NVALID returns true if the match is fully contained within the frame and false otherwise. For your case, NVALID should always be true as the metric you have chosen is guaranteed to do matching as long as the template is contained within the frame. NVALS is the matrix of metric values that best matched the template image. In essence, the centre of this matrix gives you the best metric value that the matcher produced, and so this is the value that you want. You can cheat and just find what the minimum value is by:
val = min(NVALS(:));
As such, after this point you can check to see if val is less than some threshold. This I don't know what it would be. I guess something to play around with would be that if the best match was off by... say 5, then there may be something interesting to take a look at in the frame. As such, set thresh = 5.
Therefore, if val is less than thresh, then go ahead and signal your Arduino board.
Good luck!

Finding the first element less than a certain value in an unsorted vector (MATLAB)

Pretty simple, and I thought I knew what I was doing, but apparently not. Anyways.
I need to find the first element in a vector that is less than a specific value. Here is the code that I have been using:
t = 0:0.01:5;
u = ((2)*exp(-10.*t).*cos((4.*sqrt(6)).*t) + ((5)./sqrt(6)).*exp(-10.*t).*sin((4.*sqrt(6)).*t));
for a = 1:size(u)
if u(a) < (0.05)
disp(a)
break
end
end
The value that I'm trying to find is the first element less than 0.05, however, when I run my code, I don't get anything.
What could I be doing wrong?
Thanks!
#user2994291 has correctly pointed out where your loop based solution is going wrong (+1).
However I would also add that what you are trying to do can simply be accomplished by:
find(u < 0.05, 1, 'first')
Technically, the third input is not necessary - you could just use:
find(u < 0.05, 1)
However, I seem to recall reading at some point that find will work faster if you provide the third input.
The upper bound of your for loop is probably equal to 1.
In your case, u is a row vector (can't say 100% for sure in MATLAB as I only have access to GNU Octave right now), but calling size(u) will probably give back [1 501] as an answer. Your for-loop will select 1 as upper bound.
Try replacing size(u) with size(u,2) or, even better, with length(u). I get a = 24 as an answer.
Edit:
from your questions I assume you are a MATLAB beginner, therefore I strongly advise you to look into the built-in debugger (you can add breakpoints by clicking on the left vertical bar next to the desired line of code), this would have helped you identify the error with ease and will save you a lot of time in the future.

Numerical problems in Matlab: Same input, same code -> different output?

I am experiencing problems when I compare results from different runs of my Matlab software with the same input. To narrow the problem, I did the following:
save all relevant variables using Matlab's save() method
call a method which calculates something
save all relevant output variables again using save()
Without changing the called method, I did another run with
load the variables saved above and compare with the current input variables using isequal()
call my method again with the current input variables
load the out variables saved above and compare.
I can't believe the comparison in the last "line" detects slight differences. The calculations include single and double precision numbers, the error is in the magnitude of 1e-10 (the output is a double number).
The only possible explanation I could imagine is that either Matlab looses some precision when saving the variables (which I consider very unlikely, I use the default binary Matlab format) or that there are calculations included like a=b+c+d, which can be calculated as a=(b+c)+d or a=b+(c+d) which might lead to numerical differences.
Do you know what might be the reason for the observations described above?
Thanks a lot!
it really seems to be caused by the single/double mix in the calculations. Since I have switched to double precision only, the problem did not occur anymore. Thanks to everybody for your thoughts.
these could be rounding errors. you can find the floating point accuracy of you system like so:
>> eps('single')
ans =
1.1921e-07
On my system this reports 10^-7 which would explain discrepancies of your order
To ensure reproducible results, especially if you are using any random generating functions (either directly or indirectly), you should restore the same state at the beginning of each run:
%# save state (do this once)
defaultStream = RandStream.getDefaultStream;
savedState = defaultStream.State;
save rndStream.mat savedState
%# load state (do this at before each run)
load rndStream.mat savedState
defaultStream = RandStream.getDefaultStream();
defaultStream.State = savedState;