How to generate a lower frequency version of a signal in Matlab? - math

With a sine input, I tried to modify it's frequency cutting some lower frequencies in the spectrum, shifting the main frequency towards zero. As the signal is not fftshifted I tried to do that by eliminating some samples at the begin and at the end of the fft vector:
interval = 1;
samplingFrequency = 44100;
signalFrequency = 440;
sampleDuration = 1 / samplingFrequency;
timespan = 1 : sampleDuration : (1 + interval);
original = sin(2 * pi * signalFrequency * timespan);
fourierTransform = fft(original);
frequencyCut = 10; %% Hertz
frequencyCut = floor(frequencyCut * (length(pattern) / samplingFrequency) / 4); %% Samples
maxFrequency = length(fourierTransform) - (2 * frequencyCut);
signal = ifft(fourierTransform(frequencyCut + 1:maxFrequency), 'symmetric');
But it didn't work as expected. I also tried to remove the center part of the spectrum, but it wielded a higher frequency sine wave too.
How to make it right?

#las3rjock:
its more like downsampling the signal itself, not the FFT..
Take a look at downsample.
Or you could create a timeseries object, and resample it using the resample method.
EDIT:
a similar example :)
% generate a signal
Fs = 200;
f = 5;
t = 0:1/Fs:1-1/Fs;
y = sin(2*pi * f * t) + sin(2*pi * 2*f * t) + 0.3*randn(size(t));
% downsample
n = 2;
yy = downsample([t' y'], n);
% plot
subplot(211), plot(t,y), axis([0 1 -2 2])
subplot(212), plot(yy(:,1), yy(:,2)), axis([0 1 -2 2])

A crude way to downsample your spectrum by a factor of n would be
% downsample by a factor of 2
n = 2; % downsampling factor
newSpectrum = fourierTransform(1:n:end);
For this to be a lower-frequency signal on your original time axis, you will need to zero-pad this vector up to the original length on both the positive and negative ends. This will be made much simpler using fftshift:
pad = length(fourierTransform);
fourierTransform = [zeros(1,pad/4) fftshift(newSpectrum) zeros(1,pad/4)];
To recover the downshifted signal, you fftshift back before applying the inverse transform:
signal = ifft(fftshift(fourierTransform));
EDIT: Here is a complete script which generates a plot comparing the original and downshifted signal:
% generate original signal
interval = 1;
samplingFrequency = 44100;
signalFrequency = 440;
sampleDuration = 1 / samplingFrequency;
timespan = 1 : sampleDuration : (1 + interval);
original = sin(2 * pi * signalFrequency * timespan);
% plot original signal
subplot(211)
plot(timespan(1:1000),original(1:1000))
title('Original signal')
fourierTransform = fft(original)/length(original);
% downsample spectrum by a factor of 2
n = 2; % downsampling factor
newSpectrum = fourierTransform(1:n:end);
% zero-pad the positive and negative ends of the spectrum
pad = floor(length(fourierTransform)/4);
fourierTransform = [zeros(1,pad) fftshift(newSpectrum) zeros(1,pad)];
% inverse transform
signal = ifft(length(original)*fftshift(fourierTransform),'symmetric');
% plot the downshifted signal
subplot(212)
plot(timespan(1:1000),signal(1:1000))
title('Shifted signal')
Plot of original and downshifted signals http://img5.imageshack.us/img5/5426/downshift.png

Related

rand() in range returning numbers outside of the range

In my program, I have to find two random values with certain conditions:
i needs to be int range [2...n]
k needs to be in range [i+2...n]
so I did this:
i = rand() % n + 2;
k = rand() % n + (i+2);
But it keeps giving me wrong values like
for n = 7
I get i = 4 and k = 11
or i = 3 and k = 8
How can I fix this?
The exact formula that I use in my other program is:
i = min + (rand() % (int)(max - min + 1))
Look here for other explanation
As the comments say, your range math is off.
You might find it useful to use a function to work the math out consistently each time. e.g.:
int RandInRange(int x0, int x1)
{
if(x1<=x0) return x0;
return rand() % (x1-x0+1) + x0;
}
then call it with what you want:
i = RandInRange(2,n);
k = RandInRange(i+2,n);

Need help wit heartrate calculation for watch

So I'm trying to animate a fake heartbeat for my Android wear watchface. I have an API that grabs the heartrate in BPM and the current millisecond now I'm trying to use an equation to make an image "beat" to the BPM. Here's the psuedocode:
IF (Millis / HeartRate) % (1000 / HeartRate) <= 1)
Opacity = 100;
ELSE
Opacity = 75;
ENDIF
I'm really not sure if I calculated it properly. I don't think the image is properly flashing at the correct rate. Any help with the math would be appreciatred!
A value in BPM is a frequency, rather than a period of time:
b BPM = b / 60s = b/60 * s^-1
The period of the oscillation is
T = 1/f = 60s / b = 60/b s
If we have a time in milliseconds, then we can work out the modulo vs the period:
remainderInSeconds = CurrentTimeInSeconds % T
= (CurrentTimeInMilliseconds * 1e-3) % T
= (CurrentTimeInMilliseconds * 1e-3) % (60/BeatsPerMinute)
fraction = remainderInSeconds / Period
= [(CurrentTimeInMilliseconds * 1e-3) % T] / T
= (CurrentTimeInMilliseconds * 1e-3 / T) % 1
= (CurrentTimeInMilliseconds * 1e-3 / (60/BeatsPerMinute)) % 1
= (CurrentTimeInMilliseconds * 1e-3 * BeatsPerMinute / 60)) % 1
= (CurrentTimeInMilliseconds * BeatsPerMinute / 60e3)) % 1
Then you can check whether the fraction is below your threshold; if you want the pulse to last a 20th of the period, then check if fraction < 1/20.
Alternatively just calculate the remainder in seconds, if you want the pulse to last a specific amount of time rather than a portion of the period.
I managed to compile a new code using a different variable from the watch API. This other variable is essentially a number between 0 and 359 which steps up at mere decimals per frame. (The variable is normally used for a smooth motion second hand).
I also decided to use a sine wave and RGB shaders instead of opacity. Here is the new code
Green = 0
Blue = 0
Red = 100 * math.sin(HeartRate * SecondsRotationSmooth / 60)
Using this particular variable isn't ideal, but it at least gives me a better looking code. If anyone wants to give a better answer please do!

Uniformly distribute x points inside a circle

I would like to uniformly distribute a predetermined set of points within a circle. By uniform distribution, I mean they should all be equally distanced from each other (hence a random approach won't work). I tried a hexagonal approach, but I had problems consistently reaching the outermost radius.
My current approach is a nested for loop where each outer iteration reduces the radius & number of points, and each inner loop evenly drops points on the new radius. Essentially, it's a bunch of nested circles. Unfortunately, it's far from even. Any tips on how to do this correctly?
The goals of having a uniform distribution within the area and a uniform distribution on the boundary conflict; any solution will be a compromise between the two. I augmented the sunflower seed arrangement with an additional parameter alpha that indicates how much one cares about the evenness of boundary.
alpha=0 gives the typical sunflower arrangement, with jagged boundary:
With alpha=2 the boundary is smoother:
(Increasing alpha further is problematic: Too many points end up on the boundary).
The algorithm places n points, of which the kth point is put at distance sqrt(k-1/2) from the boundary (index begins with k=1), and with polar angle 2*pi*k/phi^2 where phi is the golden ratio. Exception: the last alpha*sqrt(n) points are placed on the outer boundary of the circle, and the polar radius of other points is scaled to account for that. This computation of the polar radius is done in the function radius.
It is coded in MATLAB.
function sunflower(n, alpha) % example: n=500, alpha=2
clf
hold on
b = round(alpha*sqrt(n)); % number of boundary points
phi = (sqrt(5)+1)/2; % golden ratio
for k=1:n
r = radius(k,n,b);
theta = 2*pi*k/phi^2;
plot(r*cos(theta), r*sin(theta), 'r*');
end
end
function r = radius(k,n,b)
if k>n-b
r = 1; % put on the boundary
else
r = sqrt(k-1/2)/sqrt(n-(b+1)/2); % apply square root
end
end
Might as well tag on my Python translation.
from math import sqrt, sin, cos, pi
phi = (1 + sqrt(5)) / 2 # golden ratio
def sunflower(n, alpha=0, geodesic=False):
points = []
angle_stride = 360 * phi if geodesic else 2 * pi / phi ** 2
b = round(alpha * sqrt(n)) # number of boundary points
for k in range(1, n + 1):
r = radius(k, n, b)
theta = k * angle_stride
points.append((r * cos(theta), r * sin(theta)))
return points
def radius(k, n, b):
if k > n - b:
return 1.0
else:
return sqrt(k - 0.5) / sqrt(n - (b + 1) / 2)
# example
if __name__ == '__main__':
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
points = sunflower(500, alpha=2, geodesic=False)
xs = [point[0] for point in points]
ys = [point[1] for point in points]
ax.scatter(xs, ys)
ax.set_aspect('equal') # display as square plot with equal axes
plt.show()
Stumbled across this question and the answer above (so all cred to user3717023 & Matt).
Just adding my translation into R here, in case someone else needed that :)
library(tibble)
library(dplyr)
library(ggplot2)
sunflower <- function(n, alpha = 2, geometry = c('planar','geodesic')) {
b <- round(alpha*sqrt(n)) # number of boundary points
phi <- (sqrt(5)+1)/2 # golden ratio
r <- radius(1:n,n,b)
theta <- 1:n * ifelse(geometry[1] == 'geodesic', 360*phi, 2*pi/phi^2)
tibble(
x = r*cos(theta),
y = r*sin(theta)
)
}
radius <- function(k,n,b) {
ifelse(
k > n-b,
1,
sqrt(k-1/2)/sqrt(n-(b+1)/2)
)
}
# example:
sunflower(500, 2, 'planar') %>%
ggplot(aes(x,y)) +
geom_point()
Building on top of #OlivelsAWord , here is a Python implementation using numpy:
import numpy as np
import matplotlib.pyplot as plt
def sunflower(n: int, alpha: float) -> np.ndarray:
# Number of points respectively on the boundary and inside the cirlce.
n_exterior = np.round(alpha * np.sqrt(n)).astype(int)
n_interior = n - n_exterior
# Ensure there are still some points in the inside...
if n_interior < 1:
raise RuntimeError(f"Parameter 'alpha' is too large ({alpha}), all "
f"points would end-up on the boundary.")
# Generate the angles. The factor k_theta corresponds to 2*pi/phi^2.
k_theta = np.pi * (3 - np.sqrt(5))
angles = np.linspace(k_theta, k_theta * n, n)
# Generate the radii.
r_interior = np.sqrt(np.linspace(0, 1, n_interior))
r_exterior = np.ones((n_exterior,))
r = np.concatenate((r_interior, r_exterior))
# Return Cartesian coordinates from polar ones.
return r * np.stack((np.cos(angles), np.sin(angles)))
# NOTE: say the returned array is called s. The layout is such that s[0,:]
# contains X values and s[1,:] contains Y values. Change the above to
# return r.reshape(n, 1) * np.stack((np.cos(angles), np.sin(angles)), axis=1)
# if you want s[:,0] and s[:,1] to contain X and Y values instead.
if __name__ == '__main__':
fig, ax = plt.subplots()
# Let's plot three sunflowers with different values of alpha!
for alpha in (0, 1, 2):
s = sunflower(500, alpha)
# NOTE: the 'alpha=0.5' parameter is to control transparency, it does
# not have anything to do with the alpha used in 'sunflower' ;)
ax.scatter(s[0], s[1], alpha=0.5, label=f"alpha={alpha}")
# Display as square plot with equal axes and add a legend. Then show the result :)
ax.set_aspect('equal')
ax.legend()
plt.show()
Adding my Java implementation of previous answers with an example (Processing).
int n = 2000; // count of nodes
Float alpha = 2.; // constant that can be adjusted to vary the geometry of points at the boundary
ArrayList<PVector> vertices = new ArrayList<PVector>();
Float scaleFactor = 200.; // scale points beyond their 0.0-1.0 range for visualisation;
void setup() {
size(500, 500);
// Test
vertices = sunflower(n, alpha);
displayTest(vertices, scaleFactor);
}
ArrayList<PVector> sunflower(int n, Float alpha) {
Double phi = (1 + Math.sqrt(5)) / 2; // golden ratio
Double angle = 2 * PI / Math.pow(phi, 2); // value used to calculate theta for each point
ArrayList<PVector> points = new ArrayList<PVector>();
Long b = Math.round(alpha*Math.sqrt(n)); // number of boundary points
Float theta, r, x, y;
for (int i = 1; i < n + 1; i++) {
r = radius(i, n, b.floatValue());
theta = i * angle.floatValue();
x = r * cos(theta);
y = r * sin(theta);
PVector p = new PVector(x, y);
points.add(p);
}
return points;
}
Float radius(int k, int n, Float b) {
if (k > n - b) {
return 1.0;
} else {
Double r = Math.sqrt(k - 0.5) / Math.sqrt(n - (b+1) / 2);
return r.floatValue();
}
}
void displayTest(ArrayList<PVector> points, Float size) {
for (int i = 0; i < points.size(); i++) {
Float x = size * points.get(i).x;
Float y = size * points.get(i).y;
pushMatrix();
translate(width / 2, height / 2);
ellipse(x, y, 5, 5);
popMatrix();
}
}
Here's my Unity implementation.
Vector2[] Sunflower(int n, float alpha = 0, bool geodesic = false){
float phi = (1 + Mathf.Sqrt(5)) / 2;//golden ratio
float angle_stride = 360 * phi;
float radius(float k, float n, float b)
{
return k > n - b ? 1 : Mathf.Sqrt(k - 0.5f) / Mathf.Sqrt(n - (b + 1) / 2);
}
int b = (int)(alpha * Mathf.Sqrt(n)); //# number of boundary points
List<Vector2>points = new List<Vector2>();
for (int k = 0; k < n; k++)
{
float r = radius(k, n, b);
float theta = geodesic ? k * 360 * phi : k * angle_stride;
float x = !float.IsNaN(r * Mathf.Cos(theta)) ? r * Mathf.Cos(theta) : 0;
float y = !float.IsNaN(r * Mathf.Sin(theta)) ? r * Mathf.Sin(theta) : 0;
points.Add(new Vector2(x, y));
}
return points.ToArray();
}

Getting a cube with X volume in scilab or MATLAB?

I have a scilab program for averaging a 3D matrix and it works ok.However, instead of having the average just be a set value.I want it to be a certain sum of mass(sum(n*n*n).
K = 100
N = 5
A = 1
mid = floor(N/2)
volume = rand(K, K, K)
cubeCount = floor( K / N )
for x=0:cubeCount­1
for y=0:cubeCount­1
for z=0:cubeCount­1
// Get a cube of NxNxN size
cube = 20;
//Calculate the average value of the voxels in the cube
avg = sum( cube ) / (N * N * N);
// Assign it to the center voxel
volume( N*x+mid+1, N*y+mid+1, N*z+mid+1 ) = avg
end
end
end
disp( volume )
If anyone has a simple solution to this, please tell me.
You seem to have just about said it your self. All you would need to do would be change cube to equal.
cube = while sum(A * A * A) < 10,
A=A+1;
This will give you the correct sum of mass of the voxels.

Modifying multiplying calculation to use delta time

function(deltaTime) {
x = x * FACTOR; // FACTOR = 0.9
}
This function is called in a game loop. First assume that it's running at a constant 30 FPS, so deltaTime is always 1/30.
Now the game is changed so deltaTime isn't always 1/30 but becomes variable. How can I incorporate deltaTime in the calculation of x to keep the "effect per second" the same?
And what about
function(deltaTime) {
x += (target - x) * FACTOR; // FACTOR = 0.2
}
x = x * Math.pow(0.9, deltaTime*30)
Edit
For your new update:
x = (x-target) * Math.pow(1-FACTOR, deltaTime*30) + target;
To show how I got there:
Let x0 be the initial value, and xn be the value after n/30 seconds. Also let T=target, F=factor. Then:
x1 = x0 + (T-x0)F = (1-F)x0 + TF
x2 = (1-F)x1 + TF = (1-F)^2 * x0 + (1-F)TF + TF
Continuing with x3,x4,... will show:
xn = (1-F)^n * x0 + TF * (1 + (1-F) + (1-F)^2 + ... + (1-F)^(n-1))
Now substituting the formula for the sum of a geometric sequence will give the result above. This really only proves the result for integer n, but it should work for all values.
x = x * powf(0.9, deltaTime / (1.0f / 30.0f))

Resources