WebAudio LFO: shift range from {-1, 1} to {0, 1} - web-audio-api

Every tutorial on WebAudio LFOs creates an Oscillator for the LFO which is then routed to the gain parameter of a Gain node.
But AFAIK oscillators produce output from -1 to 1 so for half the cycle we are sending a negative value to the gain multiplier. At best this is clipped to a minimum gain of 0 at worst it goes into the negative effectively doubling up the frequency of the modulating wave.
How do you set up a simple LFO then that oscillates from 0 to 1 at the expected frequency?

You can combine an OscillatorNode with a ConstantSourceNode to achieve the desired effect.
const oscillatorNode = new OscillatorNode(context);
const constantSourceNode = new ConstantSourceNode(context);
const gainNode = new GainNode(context, { gain: 0.5 });
oscillatorNode.connect(gainNode);
constantSourceNode.connect(gainNode);
gainNode.connect(context.destination);
oscillatorNode.start();
constantSourceNode.start();
As you said the OscillatorNode will oscillate between -1 and 1. The ConstantSourceNode outputs a constant signal with the value 1. If we combine these two nodes we get a signal oscillating between 0 and 2. We can then use a GainNode to divide that signal by 2. The result will be a signal oscillating between 0 and 1.

Related

Why my PPO RL Agent action still passing the upper and lower limit in Matlab/Simulink?

I am using default Matlab rappresentation of PPO Agent, I want that one of my action only in range 0 - 1 and the other in range -1 - 1. I already set up my UpperLimit to 1, and LowerLimit to 0 or -1.
obsInfo = rlNumericSpec([17 1]);
actInfo = rlNumericSpec([5 1], ...
"UpperLimit", 1, ...
"LowerLimit",[0; -1; -1; -1; -1]);
env = rlSimulinkEnv("test_2", "test_2/agent",obsInfo, actInfo, "UseFastRestart", "off");
ppo_opt = rlPPOAgentOptions("SampleTime", 0.01);
agent_ppo = rlPPOAgent(obsInfo, actInfo, ppo_opt);
But as you can see, my action still can passing the limit (scope 1 should be in range 0 - 1 , scope 5 in range -1 - 1). This
happen for all action signal. If I change my Agent (e.g. with DDPG) this not happen. How can i fix that ?
Scope rapresenting two action dynamic of RL Agent
If ur actor is in continuous space, it will have two out puts. One is mean and second is standard devation. If standard devation path on ur actor gives posetiva value, ur actor will deviate randomly, the larger the standard devation the larger the devation. So try to make standard devation path of ur actor give zero value. Eg if sd=0.1, mean =0, then think as if actual out out is between -0.1 and 0.1.( it's just an example not exact calculation)

Removing of signals in the same frequency

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

Neural Network can't learn XOR

I've created a neural network, with the following structure:
Input1 - Input2 - Input layer.
N0 - N1 - Hidden layer. 3 Weights per node (one for bias).
N2 - Output layer. 3 Weights (one for bias).
I am trying to train it the XOR function with the following test data:
0 1 - desired result: 1
1 0 - desired result: 1
0 0 - desired result: 0
1 1 - desired result: 0
After training, the mean square error of test (when looking for a 1 result) {0, 1} = 0, which is good I presume. However the mean square error of test (when looking for a 0 result) {1, 1} = 0.5, which surely needs to be zero. During the learn stage I notice the MSE of true results drops to zero within the first few epochs, whereas MSE of false results lingers around 0.5.
I'm using back propagation to train the network, with a sigmoid function. The issue is that when I test any combination after the training, I always get a 1.0 result ouput. - The network seems to learn very fast, even with an extremely small learning rate.
If it helps, here is the weights that are produced:
N0-W0 = 0.5, N0-W1 = -0.999, N0-W2 = 0.304 (bias) - Hidden Layer
N1-W0 = 0.674, N1-W1 = -0.893, N1-W2 = 0.516 (bias) - Hidden Layer
N2-W0 = -0.243, N2-W1 = 0.955, N3-W2 = 0.369 (bias) - Output node
Thanks.
These are some steps which can help solve your problem:
Change your activation function. Here is a similar question which I answered using relu as the activation function: Neural network XOR gate not learning
Increase the the number of epochs.
Change your learning rate to a larger suitable value, so that you can reach convergence faster. You can find more info here:
How to determine the learning rate and the variance in a gradient descent algorithm?

How to identify timestamps (indices) of multiple threshold crossings in continuous data

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.

Scale Factor in Matlabs `conv()`

I have the following code which is used to deconvolve a signal. It works very well, within my error limit...as long as I divide my final result by a very large factor (11000).
width = 83.66;
x = linspace(-400,400,1000);
a2 = 1.205e+004 ;
al = 1.778e+005 ;
b1 = 94.88 ;
c1 = 224.3 ;
d = 4.077 ;
measured = al*exp(-((abs((x-b1)./c1).^d)))+a2;
rect = #(x) 0.5*(sign(x+0.5) - sign(x-0.5));
rt = rect(x/83.66);
signal = conv(rt,measured,'same');
check = (1/11000)*conv(signal,rt,'same');
Here is what I have. measured represents the signal I was given. Signal is what I am trying to find. And check is to verify that if I convolve my slit with the signal I found, I get the same result. If you use what I have exactly, you will see that the check and measured are off by that factor of 11000~ish that I threw up there.
Does anyone have any suggestions. My thoughts are that the slit height is not exactly 1 or that convolve will not actually effectively deconvolve, as I request it to. (The use of deconv only gives me 1 point, so I used convolve instead).
I think you misunderstand what conv (and probably also therefore deconv) is doing.
A discrete convolution is simply a sum. In fact, you can expand it as a sum, using a couple of explicit loops, sums of products of the measured and rt vectors.
Note that sum(rt) is not 1. Were rt scaled to sum to 1, then conv would preserve the scaling of your original vector. So, note how the scalings pass through here.
sum(rt)
ans =
104
sum(measured)
ans =
1.0231e+08
signal = conv(rt,measured);
sum(signal)
ans =
1.0640e+10
sum(signal)/sum(rt)
ans =
1.0231e+08
See that this next version does preserve the scaling of your vector:
signal = conv(rt/sum(rt),measured);
sum(signal)
ans =
1.0231e+08
Now, as it turns out, you are using the same option for conv. This introduces an edge effect, since it truncates some of the signal so it ends up losing just a bit.
signal = conv(rt/sum(rt),measured,'same');
sum(signal)
ans =
1.0187e+08
The idea is that conv will preserve the scaling of your signal as long as the kernel is scaled to sum to 1, AND there are no losses due to truncation of the edges. Of course convolution as an integral also has a similar property.
By the way, where did that quoted factor of roughly 11000 come from?
sum(rt)^2
ans =
10816
Might be coincidence. Or not. Think about it.