Swift - create sine waves with high frequencies - swift

I have the following problem: for the sake of amplitude modulation, I want to generate a sine wave with a given frequency. For lower frequencies (such as 440 Hz) the algorithm works well, but dealing with high frequencies (for example 20.000 Hz), I get additional noises of lower frequencies, increasing with the time - I mean longer I play the signal, more and more unwanted frequencies appear - and the signal is thus distorted.
Here's the essence of my algorithm
let methodStart = NSDate()
let n = vDSP_Length(1024)
let page: [Float] = (0 ..< n).map {_ in
let val: Float = sin(2.0 * .pi * 20000.0 / 44100 * Float(index))
index += 1
return val
}
let methodFinish = NSDate()
let executionTime = methodFinish.timeIntervalSince(methodStart as Date)
print("Execution time: \(executionTime)") // 0.0005 s
As you can see, I work with a loop - later the page array is used to generate the correspondent tone.
I did measure the execution time which looks like this:
Execution time: 0.0004639625549316406
Execution time: 0.000661015510559082
Execution time: 0.0005699396133422852
Execution time: 0.00047194957733154297
Execution time: 0.0005259513854980469
Execution time: 0.00047194957733154297
Execution time: 0.0005289316177368164
When we talk about the signal frequency of 20.000 Hz, the execution time should not be an issue, as during approx. 0.0005 s, a signal period fits more or less 10 times into the execution time range -> 1 : 20.000 = 0.00005.
My question: how can I achieve a pure signal?
Should I work with pointers? If so, how can I do so in my case?

Related

TV has not function to detect dominant CycleLength. Script has some problems and I cannot find them

The code has an array or loop error or cannot use the information. I want to calculate for 1 to 100 all cycles. And from these Cycles it should find out the most dominant cycle length and plot this dominant one to the chart. Better would be to get the 3 most dominant cycles and put them together into one plotted line. Please help! unfortunately
TV has no functions for detecting dominant cycles and this should solve the problem but it hast some script Problems.
//#version=5
// Import the ta-lib library
indicator("ta-lib")
// Define the period range for the analysis
periodStart = 1
periodEnd = 100
// Define the data series
dataSeries = close
// Create an array to store the magnitude of the DFT for each period
magnitudeArray = array.new<float>(periodEnd)
// Loop over the periods
for period = periodStart to periodEnd
// Initialize the real and imaginary parts of the DFT for each period
re = 0.0
im = 0.0
// Loop over the data for each period
for i = 0 to period-1
re := re + dataSeries[i]*math.cos(-2*math.pi*i/period)
im := im + dataSeries[i]*math.sin(-2*math.pi*i/period)
// Calculate the magnitude of the complex numbers for each period
magnitudeArray[period] := math.sqrt(re*re + im*im)
// Initialize a variable to store the maximum magnitude and its corresponding period
maxMagnitude = 0.0
dominantCyclePeriod = 0
// Loop over the magnitude array to find the period with the highest magnitude
for period = periodStart to periodEnd
if array.max(magnitudeArray[period]) > maxMagnitude
maxMagnitude = array.max(magnitudeArray[period])
dominantCyclePeriod = period
// Plot the dominant cycle period on the chart
plot(dominantCyclePeriod)

Getting the correct output units from the PLOMB (Lomb-scargle periodogram) function

I am trying to analyze timeseries of wheel turns that were sampled at 1 minute intervals for 10 days. t is a 1 x 14000 array that goes from .1666 hours to 240 hours. analysis.timeseries.(grp).(chs) is a 1 x 14000 array for each of my groups of interest and their specific channels that specifize activity at each minute sampled. I'm interested in collecting the maximum power and the frequency it occurs at. My problem is I'm not sure what units f is coming out in. I would like to have it return in cycles per hour and span to a maximum period of 30 hours. I tried to use the Galileo example in the documentation as a guide, but it didn't seem to work.
Below is my code:
groups = {'GFF' 'GMF' 'SFF' 'SMF'};
chgroups = {chnamesGF chnamesGM chnamesSF chnamesSM};
t1 = (t * 3600); %matlab treats this as seconds so convert it to an hour form
onehour = seconds(hours(1));
for i = 1:4
grp = groups{1,i};
chn = chgroups{1,i};
for channel = 1:length(chn)
chs = chn{channel,1};
[pxx,f]= plomb(analysis.timeseries.(grp).(chs),t, 30/onehour,'normalized');
analysis.pxx.(grp).(chs) = pxx;
analysis.f.(grp).(chs) = f;
analysis.lsp.power.(grp).(chs) = max(pxx);
[row,col,v] = find(analysis.pxx.(grp).(chs) == analysis.lsp.power.(grp).(chs));
analysis.lsp.tau.(grp).(chs) = analysis.f.(grp).(chs)(row);
end
end
Not really an answer but it is hard to put a image in a comment.
Judging by this (plomb manual matlab),
I think that pxx is without dimension as for f is is the frequency so 1/(dimension of t) dimension. If your t is in hours I would say h^-1.
So I'd rather say try
[pxx,f]= plomb(analysis.timeseries.(grp).(chs),t*30.0/onehour,'normalized');

Maximum of a part of a signal

In a signal created like so:
Tinitial =0;
Tfinal = 1;
NbEch = 300;
Tech = (Tfinal - Tinitial)/(NbEch-1);
t = Tinitial : Tech: Tfinal; % time vector
signal = sin(2*pi*t*3) + 0.25*sin(2*pi*t*50) + randn(size(t))/10;
figure
plot(t,signal)
I want to calculate the signal maximum between 0% and 10% of the time and between 50% and 60% of the time. I've tried using ginput on the figure, but want this to be done automatically because I have several curves of the same type in a loop.
Calculate the time percentages
tpct = (t-Tinitial)/(Tfinal - Tinitial);
Calculate maximums using logical indexing and the percentage vector we just made.
sigMax0_to_10 = max( signal(tpct >= 0.0 & tpct <= 0.1) ); % max between 0% - 10% time
sigMax50_to_60 = max( signal(tpct >= 0.5 & tpct <= 0.6) ); % max between 50% - 60% time
You could easily adapt this to have your upper and lower thresholds in an array and loop over them.

What's wrong with my code in Matlab?

I want to play all frequencies given in matrix(FrTm) with its duration.The actual duration is one second but each frequency has to play for 3 of 1/18 and 6 of 1/18 seocnd such as given in matrix(FrTm).
function Music()
Fs=44100;
T=1/Fs;
M = zeros(1,88);
for I=7:88,
M(I) = round(36.8*(2^(1/12))^(I-6));
end
Signal=[];
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
t=0:1/18:1;
for i=1:length(FrTm),
M(i)=FrTm(i);
Z=M(i);
data= sin(2*pi*Z/Fs*t);
signal=[data;signal];
end
stem(Signal);
sound (Signal, 44100);
end
The classical way to make a sound with a given frequency (f) and sample frequency (Fs) is to make a time vector with step 1/Fs:
time = 0:1/Fs:D;
Where Dis the duration of the signal. The signal itself is then:
signal = sin(2*pi*f.*time)
In this case the total time is fixed, not the time of each signal. The total time is denoted with T, and the total time vector is made as
time = 0:1/Fs:T;
The sum of the second column is the total number of units the vector time needs to be divided in, e.g. 50, 3 means that a signal at 50 Hz needs to be played for 3 units. This means we only need a time vector of the length of 3 units:
t = time(1:floor(end*duration/s));
Where duration is the number of units for this part and s is the total number of units. The signal is then simply, as stated above,
data = sin(2*pi*f*t);
The data is then appended to the whole signal. The complete code, looks like this:
Fs = 44100; % sample frequency [Hz]
T = 3; % total duration [s]
time = 0:1/Fs:T;
% matrix with frequencies and duration
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
s = sum(FrTm(:,2));
[m, ~] = size(FrTm);
signal = [];
for i=1:m
freq = FrTm(i,1);
duration = FrTm(i,2);
t = time(1:floor(end*duration/s));
data = 10*sin(2*pi*freq.*t);
signal = [data signal];
end
stem(signal);
sound(signal, 44100);
Note instead of declaring time in the beginning, it is possible to make a new vector each time you run through the loop. In that case omit time = 0:1/Fs:T; and change t = time(1:floor(end*duration/s)); to t = 0:1/Fs:floor(end*duration/s);
function Music()
Fs=44100;
T=1/Fs;
M = zeros(1,88);
for I=7:88,
M(I) = round(36.8*(2^(1/12))^(I-6));
end
Signal=[];
FrTm=[50 3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
for i=1:length(FrTm),
%---------------------------------------------------
% complete the function
freq = FrTm(i,1);
duration = FrTm(i,2);
time =0:1/Fs:1; % change the 1 to change total duration
s = sum(FrTm(:,2));
t = time(1:floor(end*duration/s));
data = sin(2*pi*freq.*t);
Signal = [data Signal];
end
stem(Signal);
sound (Signal, 44100);
end
This is the exact code what i wanted ViG can you please remove this tak tak sound it just a noise actually how to use envelope function to remove thid tak tak sound in music code is following.
Fs=44100;
T=1/Fs;
M=zeros(1,88);
for I=7:88
M(I)=round(36.8*(2^(1/12))^(I-6));
end
signal=[];
FrTm=[50,3;50,3;52,3;54,3;50,3;54,3;52,3;45,3;50,3;50,3;52,3;54,3;50,6;
49,3;1,3;50,3;50,3;52,3;54,3;55,3;54,3;52,3;50,3;49,3;45,3;47,3;49,3;50,6;
50,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;1,3;45,5;47,1;45,3;43,3;42,6;
45,3;1,3;47,5;49,1;47,3;45,3;47,3;49,3;50,3;47,3;45,3;50,3;49,3;52,3;50,6;
50,6];
for i=1:length(FrTm)
x=FrTm(i,1);
y=FrTm(i,2);
F=M(x);
time=0:1/Fs:y/18;
sinewave=sin(2*pi*F*time);
signal=[signal sinewave];
end
stem(signal)
sound(signal,Fs)

using aero.animation for video

I'm trying to use aero.animation to animate a missile motion in matlab.
When I use the following code it plays the video but saves only the first frame.
*data is in form of [time, x, y, angle] matrix where all time, x, y and angle are nx1 vectors which I calculated beforehand. In my case n = 1312 and I've taken x and y as zeros of column vectors. angle is the fifth column of SOLUTION which is a matrix of 1312x7, I had calculate before.
data = [time, zeros(length(time), 1), zeros(length(time), 1), SOLUTION(:, 5)];
h=Aero.Animation;
f=figure;
h.Figure=f;
h.initialize();
h.FramesPerSecond=10
h.TimeScaling = 5;
idx1=h.createBody('testrocket.ac','ac');
h.bodies{1}.TimeseriesSourceType='Array3DoF';
h.bodies{1}.timeseriesSource=data;
h.Camera.offset=[-150 -150 0];
h.show()
h.VideoRecord = 'on';
h.VideoQuality = 50;
h.VideoCompression = 'Motion JPEG AVI'
h.VideoFilename = 'astMotion_JPEG';
h.play()
h.VideoRecord='off';
The code looks like this now, yet the video still recording same image for few seconds insted of recording the actual video with the missile movment. ( when i play the record video it shows like frozen situation).
Thanks.
I have found a solution but you have to know the time duration of your animation.
Now your problem is caused by running h.VideoRecord = 'off'; command shortly after h.play command but h.VideoRecord = 'off'; command doesn' t wait for the previous command finish. Anyway you can use pause() function to avoid the problem.
% // ...
h.play()
pause(timeDurationOfAnimation) % // timeDurationOfAnimation -> time unit in seconds
h.VideoRecord = 'off';
EDIT: Time duration of animation/video depends on you specified values of FramesPerSecond and TimeScaling properties.
The combination of FramesPerSecond and TimeScaling property determine the time step of the simulation. Your settings result in a time step of approximately 0.5 s.
+++ More Explanation:
My data is 100x4 matrix means length of time vector is 100. Time resolution is 0.1 second so time vector like that Time = [0, 0.1, 0.2, 0.3, ..., 9.8, 9.9, 10]'. If I use your time set up which is FramesPerSecond = 10 and TimeScaling = 5, I get 2 seconds of video. Because TimeScaling = 5 means display 5 data pack in per second, but one data pack contains 10 frames so according to your set up animation displays 50 frame per second. My whole data contains 100 frames so 100/50 = 2 seconds so time duration of animation/video is 2 seconds. Remember TimeScaling is due to speeding up the animation and you record your animation as speeded up one.
My suggestion is that specify value of FramesPerSecond according to frequency of your Time update:
% // ...
h.FramesPerSecond = 1 / ( data(2, 1) - data(1, 1) ) % // According to my Time resolution that would be 10;
h.TimeScaling = 1;
% // ...
pause( data(end, 1) )
h.VideoRecord = 'off';