Generate ramp audio signal of frequencies within specific duration - matlab

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

Related

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

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)

glitch when I try to crossfade between two sinusoidal signals back and forth in Matlab

I'm trying to create some functions in Matlab that is going to record a tone and then play it back semi-continuous. For example I want the user to be able to whistle for 2 seconds and the whistle to be dragged out to 10 seconds. I want to avoid using fancy time stretch algorithms but just use this through repetitions. I know there's issues with this but I'm doing this for experiment.
To do this, I need to crossfade the beginning and end of the sound to make it seem continuous. I have written a crossfade function that takes two signals and fades between them.
The idea is to have a sigmoid volume function that goes from 1 to 0 for the old sound and 0 to 1 for the new. I then just multiply the signal by this volume function and add the result. My understanding of the sigmoid function is that the resulting volume should be an average of the two input signals, with weight slowly moving from input signal a to input signal b, and the output amplitude should be the same as the input ones.
When I try this with two simple sinusoid input signals, however, and go back and forth between a low and high tone, I get a small "glitch" in the section just where it transfers from a low-to-high section, to a high-to-low sliding section. Where does this come from? I'm also not sure if this is only on my speakers, and I tried watching the plotted waveforms in time domain, but couldn't see anything weird happening at the specific time.
The end of the first section, and beginning of the last should have exactly the same frequency component, and nothing is moved in time, so I'm not sure where this glitch comes from.
Sample code:
(SLIGHT WARNING: This output some tones, one of which is a little bit high pitch, so maybe not play this with earphones on or with full volume).
function test()
Fs=44100;
x=1:1/Fs:2;
x=x'; %time vector
freq1 = 440; %low tone
freq2 = freq1*2^(7/12) % high tone (harmonic fifth)
Fs=44100;
x=1:1/Fs:2;
x=x'; %time vector
freq1 = 440; %low tone
freq2 = freq1*2^(7/12); % high tone (harmonic fifth)
y1 = sin(2*pi*x*freq1)
y2 = sin(2*pi*x*freq2)
res = stitchandrepeat(y1,y2, Fs);
end
function [out] = stitchandrepeat(in, in2, Fs)
lowtohigh = crossfade(in,in2,1);
hightolow = crossfade(in2,in,1);
out = [lowtohigh;hightolow];
out = [out;out];
out = [out;out];
out = [out;out];
end
function [out] = crossfade(a, b, sigmoid)
if not(size(a) == size(b))
error('Different sizes');
end
index = (1:size(a,1))';
factor = index/size(a,1);
if(sigmoid)
steepness = 5;
factor = logsig((factor-0.5)*steepness*2);
end
plot(index, factor, 'o');
out = bsxfun(#times, a, 1-factor)+bsxfun(#times, b, factor);
end
I even tried doing a second crossfade where I stitched together the end and beginning of the first and second signal, but it still sounded a little bit weird just in the transition. Any idea on how to make the transition smooth?
function [out] = stitchandrepeat2(in, in2, Fs)
lowtohigh = crossfade(in,in2,1);
hightolow = crossfade(in2,in,1);
secstofade = 0.1;
len = size(lowtohigh,1);
partsize = secstofade*Fs;
lthpart = lowtohigh((len-partsize+1):len,:);
htlpart = hightolow(1:partsize,:);
lthcropped = lowtohigh(1:len-partsize,:);
htlcropped = hightolow(partsize+1:len,:);
highfade = crossfade(htlpart, lthpart,1);
out = [lthcropped;highfade;htlcropped];
out = [out;out];
out = [out;out];
out = [out;out];
end
And how come I don't get this glitch sound in the low part of the sound? (Two different sound waves are also just concatenated there.)

creating fast successive beeps in matlab/psychtoolbox

I have to create beep arrays of differing numerosity. I determine how many beeps will be
played, the duration of each individual beep and the inter-beep duration online. However,
these all have to be played really fast, both the intervals and the durations will be in between 0.01secs-0.2secs. The sound function of matlab does not allow you to take very small breaks in between as even if you play two sound functions one after each other without putting a small break by a timer, it takes longer than the timing I need. Any ideas? I would really appreciate any help...
To guarantee a given spacing, I think that you need to assemble the waveform. I suspect a lot of variation in the time it takes to startup the sound function.
As an example, the function below should give you a good start:
function beep_series(specs)
%BEEP_SERIES Create a series of beeps
% BEEP_SERIES([FREQ_HZ, VOL, DUR_SEC, PAUSE_SEC]) creates a series of
% beeps from an N-by-4 spec matrix, where the colums represent:
% frequency
% volumne (0-1)
% beep duration
% pause duration,
freq = specs(:,1);
volume = specs(:,2);
duration = specs(:,3);
trailingGap = specs(:,4);
SAMPLE_FREQ = 8192;
totalTime = sum(duration) + sum(trailingGap);
x = zeros(ceil(totalTime*SAMPLE_FREQ),1);
curBeepStartTime = 0;
for ix = 1:length(freq)
numSamples = round(duration(ix)*SAMPLE_FREQ);
x( round(curBeepStartTime*SAMPLE_FREQ + (1:numSamples)) ) = ...
volume(ix) * sin( (1:numSamples) * (2*pi*freq(ix)/SAMPLE_FREQ) );
curBeepStartTime = curBeepStartTime + duration(ix) + trailingGap(ix);
end
sound(x, SAMPLE_FREQ)

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.