Creating a continuous tone in MATLAB whose frequency varies in real-time depending on user input - multithreading

I am currently working on a graphing program in MATLAB that takes input and maps a point to x-y space using this input. However, the program should also output a continuous tone whose frequency varies depending on the location of the point.
I was able to get the tone generation done, however could not get the tone to work continuously due to the nature of the program. (Code in between tone generations) I thought I could solve this using a parfor loop with the code that alters the frequency in one iteration of the loop, and the code that generates the tone in another but cannot seem to get it due to the following error:
Warning: The temporary variable frequency will be cleared at the
beginning of each iteration of the parfor loop. Any value assigned to
it before the loop will be lost. If frequency is used before it is
assigned in the parfor loop, a runtime error will occur. See Parallel
for Loops in MATLAB, "Temporary Variables".
In multiThreadingtest at 5 Error using multiThreadingtest (line 5) Reference to a cleared variable frequency.
Caused by:
Reference to a cleared variable
frequency.
And my code:
global frequency
frequency = 100;
parfor ii=1:2
if ii==1
Fs = 1000;
nSeconds = 5;
y = 100*sin(linspace(0, nSeconds*frequency*2*pi, round(nSeconds*Fs)));
sound(y, Fs);
elseif ii==2
frequency = 100
pause(2);
frequency = 200
pause(2);
frequency = 300
pause(2);
end
end

The solution may not come from multithreading, but from the use of another function to output a tone(audioplayer, play, stop). 'audioplayer/play' has the ability to output sounds that overlap in time. So basically, a pseudo code would be:
get the value of the input
generate/play a corresponding 5 second tone
detect if any change in the input
if no change & elapsed time close to 5 seconds
generate/play an identical 5 second tone
if change
generate a new 5 second tone
%no overlapping
stop old
play new
%overlapping (few milliseconds)
play new
stop old
The matlab code showing the 'sound'/'play' differences.
Fs = 1000;
nSeconds = 5;
frequency = 100;
y1 = 100*sin(linspace(0, nSeconds*frequency*2*pi, round(nSeconds*Fs)));
aud1 = audioplayer(y1, Fs);
frequency = 200;
y2 = 100*sin(linspace(0, nSeconds*frequency*2*pi, round(nSeconds*Fs)));
aud2 = audioplayer(y2, Fs);
% overlapping sound impossible
sound(y1, Fs);
pause(1)
sound(y2, Fs);
% overlapping sound possible
play(aud1);
pause(1);
disp('can compute here');
play(aud2);
pause(1);
stop(aud1);
pause(1);
stop(aud2);

Related

Use of fft on sound using Julia

I have some code in Julia I've just wrote:
using FFTW
using Plots
using WAV, PlotlyJS
snd, sampFreq = wavread("input.wav")
N, _ = size(snd)
t = 0:1/(N-1):1;
s = snd[:,1]
y = fft(s)
y1 = copy(y)
for i = 1:N
if abs(y1[i]) > 800
y1[i] = 0
end
end
s_new = real(ifft(y1))
wavwrite(s_new, "output1.wav", Fs = sampFreq)
y2 = copy(y)
for i = 1:N
if abs(y2[i]) < 800
y2[i] = 0
end
end
s_new = real(ifft(y2))
wavwrite(s_new, "output2.wav", Fs = sampFreq)
sticks((abs.(y1)))
sticks!((abs.(y2)))
s1,k1 = wavread("output1.wav")
s2,k2 = wavread("output2.wav")
for i = 1:N
s1[i] += s2[i]
end
wavwrite(s1, "output3.wav", Fs = sampFreq)
it's the code that reads file input.wav, next do fft on the sound, dividing it into two files output1 with only frequencies > 800 and output2 with frequencies < 800.
In next part I merge the two files into output3. I expected something similar to input, but what I get sounds terrible (I mean it sounds like input, but is quieter and with hum bigger than expected).
My question is on which part of a code I loose the most information about input and is it a way to improve it, to get as output3 something almost like input?
You appear to not understand what the fft (fast fourier transform) returns. It returns a vector of amplitudes, not frequencies. The vector's components correspond to a the amplitude of a sine wave at a frequency that you can find using the fftfreq() function, but be sure to provide the fftfreq() function with its second argument, your sampFreq variable.
To decompose the sound, then, you need to zero the vector components you do not want, based on what fftfreq() tells you the frequencies corresponding to the bins (vector postions in the vector returned by fft().
You will still see a big drop in sound quality with reversing the process with ifft, because the fft will basically average parts of the signal by splitting it into the frequency dimension's bins.
I suggest a tutorial on fft() before you fix your code further -- you can google several of these.

Fifo : acces all elements in it

my problem is pretty simple, I am using an eye tracking device, which sends gaze position every 30ms approximately. So, every 30ms, a variable smoothedCoordinates is updated.
I would like to determine, using the last X (10 for example) values of smoothedCoordinates, a zone on the screen where the user is looking at.
To do this I have to store these values of smoothedCoordinates in a container and do a process on it to determine the zone (by getting the xmin, xmax, ymin ,ymax of these X values)
.
I thought about using a FIFO, each time the variable is updated I would push the value to the front of the fifo and pop the back one, in this case my FIFO would always be the same size.
But is it possible to accede directly to all the elements of a FIFO, without popping them ?
I searched the internet and it looks like it's only possible to accede to the first element and the last one ?
.
If it isn't possible to do it with a FIFO, is there another container that would suit my needs ?
You could just use a standard array and give it FIFO like capabilities like the following
char array[20];
// prepend the array and cut off the last value
for (int i = 19 ; i >= 0 ; i--)
{
// ignore the last element, so it gets overwritten
if (i != 19) array[i+1] = array[i];
}
// add the new value to the array at the now available 1st index
array[0] = firstElement[0];

Playing consecutive pitches in MATLAB

so I've been struggling with this for a while. I am supposed to make a sequence of tones play with only one soundsc(wave,fs) call, but when I try to put the tone waves in an array, it just plays them at the same time instead of consecutively. For example:
pitch1 = sin(2*pi*freq1*t);
pitch2 = sin(2*pi*freq2*t);
pitch3 = sin(2*pi*freq3*t);
concat_pitch = [pitch1; pitch2; pitch3]; % I want them to play in order, not together
soundsc(concat_pitch, fs); % this just plays them all together
Can anyone help me out? Thanks.
Change your concatenation to form a single row vector:
concat_pitch = [pitch1, pitch2, pitch3];
Or if the concatenation you specified is important and has to stay as is, then you can loop through the rows of the 2-d matrix:
for ind=1:length(concat_pitch)
soundsc(concat_pitch(ind,:), fs);
end

Audio analysis to detect low volume periods

i have a sequence of audio files (they are currently both wav and mp3). These files consist of a beep, a pause and then the reply of a person. I need to find the reaction time between the beep and the person replying. There is a lot of data so i would like to make a program that could do this for me. Does anyone have any idea what language this could be done in, or know of any existing programs that will do this. I have looked into the wave tool in python, and can't seem to find any data that represents the low moments.
i program to function like this:
wav = open(wave file)
chunk = getNextChunk(wav)
volume = analyse(chunk)
check against threshold
if silent period, check for loud period
find difference
log time in seconds
Can anyone help me with this, i know its a very open ended question, but i have no idea where to start with this, i've programmed in java and python among others, but will use whats best, same with the sound format. Would it also be better to make the files mono?
Thanks for your help!
As to your choise of language I would personally choose Matlab. However it costs money, and as you already have experience with python the numpy module might be the right thing for you.
Based on your description of your problem, this could be one approach:
Load wav
Find envelope and smooth with a fast time constant
Threshold
Find time for beep
Find time for response
Calculate difference
Going to mono will be fine and reduce your amount of data at the same time.
I have found a solution that works, although my algorithm for detecting audio is pretty lousy, and is not very accurate. The amplitude or frequency of the sound seems to be visible, so the more digits a number has, the louder it is. I detect long sequences of digits to determine this, but one digit that doesnt fit the pattern and the cycle resets. Would be better to dermine based on the difference between the previous digits.
import wave, struct, logging
# open up a wave
w = wave.open('wavefile.WAV', 'rb')
length = w.getnframes()
rate = w.getframerate()
logging.basicConfig(filename='example.log',level=logging.DEBUG)
count = 0
start = 1
end = 0
startData = 0
endData = 0
for i in range(0,length):
waveData = w.readframes(1)
data = struct.unpack("<h", waveData)
if (start == 1):
if (len(str(int(data[0])))>=len(str(1234))):
count=count+1
else:
count=0
if (count == 100):
startData=i-100
print("Start "+str(startData/float(rate)))
count = 0
start = 0
end = 1
if (end == 1):
if (len(str(int(data[0])))<=len(str(12))):
count=count+1
else:
count=0
if (count == 10):
endData=i-10
print("End "+str(endData/float(rate)))
count = 0
start = 1
end = 0
frames=endData-startData
duration=frames/float(rate)
print("Duration: "+str(duration))

How to draw a frequency spectrum from a Fourier transform

I want to plot the frequency spectrum of a music file (like they do for example in Audacity). Hence I want the frequency in Hertz on the x-axis and the amplitude (or desibel) on the y-axis.
I devide the song (about 20 million samples) into blocks of 4096 samples at a time. These blocks will result in 2049 (N/2 + 1) complex numbers (sine and cosine -> real and imaginary part). So now I have these thousands of individual 2049-arrays, how do I combine them?
Lets say I do the FFT 5000 times resulting in 5000 2049-arrays of complex numbers. Do I plus all the values of the 5000 arrays and then take the magnitude of the combined 2049-array? Do I then sacle the x-axis with the songs sample rate / 2 (eg: 22050 for a 44100hz file)?
Any information will be appriciated
What application are you using for this? I assume you are not doing this by hand, so here is a Matlab example:
>> fbins = fs/N * (0:(N/2 - 1)); % Where N is the number of fft samples
now you can perform
>> plot(fbins, abs(fftOfSignal(1:N/2)))
Stolen
edit: check this out http://www.codeproject.com/Articles/9388/How-to-implement-the-FFT-algorithm
Wow I've written a load about this just recently.
I even turned it into a blog post available here.
My explanation is leaning towards spectrograms but its just as easy to render a chart like you describe!
I might not be correct on this one, but as far as I'm aware, you have 2 ways to get the spectrum of the whole song.
1) Do a single FFT on the whole song, which will give you an extremely good frequency resolution, but is in practice not efficient, and you don't need this kind of resolution anyway.
2) Divide it into small chunks (like 4096 samples blocks, as you said), get the FFT for each of those and average the spectra. You will compromise on the frequency resolution, but make the calculation more manageable (and also decrease the variance of the spectrum). Wilhelmsen link's describes how to compute an FFT in C++, and I think some library already exists to do that, like FFTW (but I never managed to compile it, to be fair =) ).
To obtain the magnitude spectrum, average the energy (square of the magnitude) accross all you chunks for every single bins. To get the result in dB, just 10 * log10 the results. That is of course assuming that you are not interested in the phase spectrum. I think this is known as the Barlett's method.
I would do something like this:
// At this point you have the FFT chunks
float sum[N/2+1];
// For each bin
for (int binIndex = 0; binIndex < N/2 + 1; binIndex++)
{
for (int chunkIndex = 0; chunkIndex < chunkNb; chunkIndex++)
{
// Get the magnitude of the complex number
float magnitude = FFTChunk[chunkIndex].bins[binIndex].real * FFTChunk[chunkIndex].bins[binIndex].real
+ FFTChunk[chunkIndex].bins[binIndex].im * FFTChunk[chunkIndex].bins[binIndex].im;
magnitude = sqrt(magnitude);
// Add the energy
sum[binIndex] += magnitude * magnitude;
}
// Average the energy;
sum[binIndex] /= chunkNb;
}
// Then get the values in decibel
for (int binIndex = 0; binIndex < N/2 + 1; binIndex++)
{
sum[binIndex] = 10 * log10f(sum[binIndex]);
}
Hope this answers your question.
Edit: Goz's post will give you plenty of information on the matter =)
Commonly, you would take just one of the arrays, corresponding to the point in time of the music in which you are interested. The you would calculate the log of the magnitude of each complex array element. Plot the N/2 results as Y values, and scale the X axis from 0 to Fs/2 (where Fs is the sampling rate).

Resources