What's wrong with my code in Matlab? - 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)

Related

Filtering a single sample in MATLAB

I'm attempting to create a reverb function in MATLAB and would like to filter the repeats to make them sound more natural. I have the signal processing toolbox however I get an error telling me that I cannot use the lowpass() function on single samples and MATLAB wigs out. The idea is to filter the signal every time it enters the feedback loop to simulate the absorption of high frequencies every time the sound reflects off a surface. My code looks like this:
[x,Fs] = audioread('Clap.mp3');
%Calculate delay length
secOfDelay = 0.03; %units of seconds
samplesOfDelay = secOfDelay * Fs; %sec * samples/sec = samples
%Gain for wet mix
g = 0.9;
for n = 1:length(x)
if (n - samplesOfDelay) < 1 %For no past samples, don't add the delay yet.
out(n,1) = x(n,1);
else
a(n,1) = x(n,1);
b(n,1) = x(n,1) + (g * b(n-samplesOfDelay,1));
end
end
%Add wet mix and dry mix together
out = a+b;
sound(out,Fs);
Any help would be greatly appreciated!
JDB

Matlab sound with a function for a keyboard [duplicate]

Hello I have to build a program that is able to play some piano sounds from beethoven elise
Now I have implemented the function for the frequency and the sound but it sounds strange and not at all like piano notes.
Could someone give me advice on how to fix this?
createWaveform(440,8000,2,1);
function [sinusoid] = createWaveform(frequency,fs,duration,A)
n = linspace(0,duration-1/fs,duration*fs);
sinusoid = 1:duration*fs;
for i = 1:duration*fs
sinusoid(i) = A*cos(2*pi*frequency*n(i)*(1/fs)+(2*pi).*rand(1,1));
end
end
end
Here is the part where I am attempting to build tones to the right piano note
%function [tone] = note(keynum,relDuration,fullDuration,fs)
%basetone = 440;
% frequency = basetone * nthroot(2,12)^(keynum-49);
%[tone]=createWaveform(frequency,fs,relDuration*fullDuration,1);
%end
Edit: I've deleted all my old code and wrote the following that did the job
%sound(createWaveform(1000,8000,1,1));
sound(note(24,1/2,1,8000));
function [sinusoid] = createWaveform(frequency,fs,duration,A)
Fs = fs; % samples per second
dt = 1/Fs; % seconds per sample % seconds
t = (0:dt:duration)'; % seconds
%%Sine wave:
Fc = frequency; % hertz
sinusoid = A.*cos(2*pi*Fc*t+(2*pi).*rand(1,1));
% Plot the signal versus time:
end
function [tone] = note(keynum,relDuration,fullDuration,fs)
basetone = 440;
frequency = basetone * nthroot(2,12)^(keynum-49);
tone=createWaveform(frequency,fs,relDuration*fullDuration,0.5);
end
function [E] = envel(relDuration,fullDuration,fs)
param = 0;
for i = 0:fs:relDuration*fullDuration
E(i)=relDuration*fullDuration;
i=i+1;
end
end
As mentioned in the Comments, the sound that a piano makes is quite complicated. As such this is not a Matlab challenge, just a math problem.
Now that you know this, you 'just' need to come up with a reasonable mathematical approximation, and from here it should be straight forward to implement in Matlab.
Here is something to get you started with the math:
https://dsp.stackexchange.com/questions/46598/mathematical-equation-for-the-sound-wave-that-a-piano-makes

How to increase time by 1s and replace old DT_i with the new one

I'm trying to calculate the DT value from a model I set up on Sim4Life. Firstly, i'd like to say that I am a complete beginner and I am trying to understand how programming works in general.
Now, I have a function with some constants and two variables, the one being time Dt (starting from 1 sec to 900 secs) and the other being the initial DT_i value. I want to calculate the increase of temperature for every second and create a loop that replaces the DT_i value with the DT_1_i value and also calculates the increased temperature DT_i_1. The function looks like this: DT_1_i=DT_i+Dt.
I know it is a very simple problem but I couldn't work my way through other similar questions. Any help would be appreciated.
Temperature variation:
You need initial temperature variation , I used 0
T(i+1) stands for Next temperature variation
T(i) stands for present temperature variation
i stands for time step, dt
Read through comment in my code
Time
Use for loop to set the time for i = 1 : 900 %Temperature increase end
i =1:900 just means
first run use time = 1s,
second run time = 1+1 = 2
so on till 900
The code is as follow
% Initial Temperature variation is set to zero, unless you have some data
d = 1.3;
c = 3.7;
S_i = 3*10^3;
t_reg = 900;
%Time
t = 1:900;
% Length oftime to help me know the size of the variable needed to
% initialize
l = length(t);
% Initialize variable that used to store DT it helps speed up
% comutation
% Initial Temperature variation is set to zero, unless you have some data
DT = zeros(1, l);
for i = 1:900
% the value of i represent dt, first run i = 1, dt = 1, second run
% i = 2 and dt = 2 so on
if i == 900
%do nothing already reached the last index 900, i+1 = 901 will be
%out of range
else
DT(i+1) = DT(i) + (i./t_reg).*(d.*sqrt(c*S_i)-DT(i+1));
end
end

Generate ramp audio signal of frequencies within specific duration

I wanted to generate frequencies of 10hz to 1000hz with a step of 10hz, let's say within 5s (all frequencies equally distributed within the time frame). How do I achieve this from the individual frequency generator function below?
function [ ] = producefeq( frequency, duration, amplitude, freqsampling )
if ~exist('freqsampling', 'var'), freqsampling = 44100; end
if ~exist('amplitude', 'var'), amplitude = 1; end
if nargin <2, error('Not enough input arguments'); end
% the frequency argument will be like this for the case above 10:10:1000
t = 0:(1/freqsampling):duration;
y = amplitude*sin(2*pi*frequency*t);
sound(y, freqsampling);
end
Thanks in advance!
You can call producefeq multiple times and use pause to wait between multiple executions.
totalDuration = 500;
frequencies = 10:10:1000;
duration = totalDuration/length(frequencies);
for i = 1:length(frequencies)
producefeq( frequencies(i), duration)
pause(duration)
end

How can I output a composite signal made of two signals with different time period at the same time on one audio channel in matlab code?

%-------------------------------------------------------------------
% Function to Generate ECG of 1 heart beat signal
function [Heartbeat,t1] = ECG_Gen (HR,pulse_width,Amp)
Fs = 48000;
delay = ((60/HR)/2)-(0.5*pulse_width);
t1 = -delay:(1/Fs):delay;
Heartbeat = Amp*tripuls (t1,pulse_width);
%-------------------------------------------------------------------
%Test Circuit configuration
function [FECG_MECG,Mixed_ECG,fastTime] = Test_Circuit (FHR,MHR)
Fs = 48000;
%FHR = 150;
%MHR = 60;
Fpulse_width = 30e-3;
Mpulse_width = 60e-3;
FAmp = 0.2;
MAmp = 0.5;
% Fetal ECG Gen
%------------------------------------------------
[FECG,FHR_Delay]= ECG_Gen (FHR,Fpulse_width,FAmp);
% Maternal ECG Gen
%------------------------------------------------
[MECG,MHR_Delay]= ECG_Gen (MHR,Mpulse_width,MAmp);
% Composite signal implementation
%------------------------------------------------
% Set parameters for Composite signal Algorithms
if length (MECG) > length (FECG) % Check for time sequences for both ECG signal
slowECG = FECG; % Set interpolation to slower rate
fastECG = MECG;
timeSeg = length(MECG);
fastTime = MHR_Delay; % Set sampling times
slowTime = FHR_Delay;
else
slowECG = MECG;
fastECG = FECG;
timeSeg = length(FECG);
fastTime = FHR_Delay;
slowTime = MHR_Delay;
end
FECG_MECG = zeros (timeSeg,2); % To hold stereo output
FECG_MECG(:,2) = fastECG(1,:); % Assign higher rate signal to one channel
% Interpolation on the slower rater sampled ECG
slowECGInterp = interp1 (slowTime,slowECG,fastTime);
slowECG = num2cell(slowECGInterp); % Conversion to cell Array in order to remove NaN
slowECG(cellfun(#(slowECG) any(isnan(slowECG)),slowECG)) = [];
slowECG = cell2mat(slowECG);
j = 1;
for i = 1:timeSeg
FECG_MECG(i,1) = slowECG(1,j);
if j == length(slowECG)
j = 0;
end
j = j+1;
end
Mixed_ECG = FECG_MECG(:,1) + FECG_MECG(:,2); % to hold mono output
%while (1)
%sound(Mixed_ECG ,Fs);
%end
%-------------------------------------------------------------------
% Test Wave script
clear all
%clc
clc
Fs = 48000;
%for i = 1:3
%toc
MHR = 60;
FHR = 200;
% Obtain ECG interpolated signal and composite
[FECG_MECG,Mixed_ECG,fastTime] = Test_Circuit (FHR,MHR);
% for test purposes
[MECG,MHR_Delay]= ECG_Gen (60,60e-3,0.5);
%t = timer ('TimerFcn','stat=false','Period',2.0);
wavwrite (FECG_MECG(:,2),Fs,'ECGwav.wav');
i = 0;
a = 1;
tic
while (1)
while (toc < 20*a)
sound (MECG,Fs);
end
toc
a = a+1;
[MECG,MHR_Delay]= ECG_Gen (60*a,60e-3,0.5);
if a > 4
break
end
end
%start(t)
%tic
%t = cputime;
%y = wavread('ECGwav.wav');
%while (1)
% sound(y,Fs);
%end
%toc
Hey Thank you very much for getting back to me, I have made use of your interpolation but still have minor problems from the reading obtained from the Monitor. Fist of all, say I have a constant signal with fixed time period say, 0.8s and I want to add composite signal of say 0.3s, I have managed to use your interpolation method to sample the 0.3s signal at the rate of my 0.8s signal. I think I have solved this issue. Second issue deals with how to combine the two signals which I have managed to do somehow but when I use a while loop in order to repeat the composite signal say over 20s, the signals obtained from the sound output isn't quite what I expected since its sounding the array of stored composite signal which contain ( signal with 0.8s = slowInterp signal of 0.3s ). I have include all the codes and functions. Basically, I need the sound output in while loop to sync with the composite signal for example: if I have a signal that repeats every 1s, I would expect to hear a beep in a while loop that runs for 10s to produce 10 beeps, etc
It is hard to tell exactly what you need, but probably doing interpolation on the sequence that is sampled at the slower rate would work for your application.
If t1s are your times from your faster sequence, and t2s are times from your slower sequence, and slow is your slower sequence then do:
slowInterp = interp1(t2s, slow, t1s);
now you will have the sequency slow sampled at the faster rate.
This is only useful for displaying the time series. If you are doing any spectral analysis, this will introduce artifacts, but that is a more advanced topic.
Using the resample function in the signal processing toolbox could also be useful.