Pitch detection by DFT grid
Acknowledgements
1. Learning Byzantine music at the Byzantine Music School of the Piraeus Metropolis (new calendar) in 1990 led me to design a project to master chant.
2. I studied DSP literature at the Eugenidis Foundation Library in the 1990s and 2004. I picked up the basics of DSP there.
3. I mastered DFT in 2016 by studying the book Understanding Digital Signal Processing by Mr. Richard Lyons, a mentor for DSP professionals.
4. I posed the question, "Can I test any frequency with DFT?" on dsp.stackexchange in 2017. *Yes* was the response given by Marcus Müller, a mentor for DSP specialists. I can now perform DFT grid, I learned.
4. I posed the question, "Can I test any frequency with DFT?" on dsp.stackexchange in 2017. *Yes* was the response given by Marcus Müller, a mentor for DSP specialists. I can now perform DFT grid, I learned.
5. I was recommended to use 16384 as the second argument in the function fft by Mr. Jeffrey Clark at matlab.
Introduction
1. I am unable to use this code in the DSP kit since I am homeless. I'm giving it away for free.
It pinpoints fundamental frequency (fundFreq), commonly referred to as pitch or the first harmonic, with far greater accuracy by using a DFT grid about fundFreq discovered by FFT or any other pitch-detecting technique. It functions as a micrometer.
My method is simple enough even for a music student to utilize; all it takes is for the user's voice pitch to be one tone (9/8) lower or higher than the frequency of the note. The Matlab's abs(fft()) function is then used to get indices up to 1.2 note's frequency. Among them, the first harmonic's abs is the biggest.
2. It should, in fact, be integrated into a project that uses a DSP kit in part.
3. There should be two sections to the project. One uses the DSP kit to execute DFT grid, while the other uses the PC's processor to execute graphics.
4. A rectangle is used to graphically indicate the interval between a musical note and its base when expressed in a unit like a 100th of a major tone (9/8). Its width indicates the duration (tempo) of the note at a given rate. Color indicates the volume or amplitude of sound. Rectangle travels to the left at a speed determined by its width and the tempo of the note. On the left side of the window, there is an arrow that moves up and down. Pitch of voice is shown by its height. To obtain a notion view the Metrw-pitch graphics.
5. A vertical scale with zero in the middle, one semitone represented by the top half, and one semitone represented by the bottom half might be designed. Zero designates the top edge of the note rectangle. This scale can perform micrometer tasks. A horizontal scroll bar is requored to enable the user to navigate back. It also needs a speed regulator.
6. We have to add a snippet in order to gauge the sound's volume. The volume of the sound also requires a third scale.
Accuracy error
1. Even the tiniest musical interval, diesis, must be given by singers, chanters, and violists. Nevertheless, projects that use FFT to determine fundFreq are unsatisfactory to musicians since fundFreq has accuracy (or inaccuracy) about a diesis.
Similar errors are made by other pitch detection techniques. The current code has an accuracy better than 0.1 diesis in detecting funbdFreq. Therefore, the user can view the pitch error of their voice in real time, eight times per second, and adjust the pitch of their voice to give diesis when this code is embedded in a project running in the DSP kit.
The issue is whether the precision of the MATLAB code running in the DSP kit is the same as that of the MATLAB online R2020b. Visit dsp.stackexchange to view Mr. Ben's response to my query query. It is positive.
2. The error is based on the Segm/SampFreq ratio. The accuracy increases with the ratio. However, the visuals' pitch iteration rate decreases.
3. FundFreq also affects error. Less fundFreq corresponds to more accuracy error. The apparent explanation for both is this: More FundFreq periods in Segm correspond to increased accuracy. Additionally, it is somewhat dependent on phase, amplitude, and upper harmonics.
General instructions
1. I advise sampling at a frequency of 96000 samples per second to avoid analog filters, which distort signals. A snippet for noise reduction is required.
2. Next, a low pass FIR filter with a 7000–8000 kHz transition band is applied.
3. SampFreq is lowered to 16,000 samples per second, with 1 sample chosen every 6.
4. Programmer is able to alter numbers.
5. See the responses to my question at dsp.stackexchange for a conical display of FFT amplitudes.
The code
format default;
SampFreq = 16000;
Segm = 1:2048;
baseFreq = 256;
noteFreq = baseFreq*100/81; % up to 2666, for 3rd harmonic < 8000
x = 1.1; % 8/9 < x < 9/8
voicePitch = x * noteFreq;
% Generating signal
FirstHarmAngles = voicePitch*2*pi/SampFreq*Segm+1.9*pi;
SinFirstHarmAngles = sin(FirstHarmAngles);
SecondHarmAngles = voicePitch*2*2*pi/SampFreq*Segm+2.9*pi;
SinSecondHarmAngles = sin(SecondHarmAngles);
ThirdHarmAngles = voicePitch*3*2*pi/SampFreq*Segm+0.3*pi;
SinThirdHarmAngles = sin(ThirdHarmAngles);
Xn=170000*SinFirstHarmAngles+220000*...
SinSecondHarmAngles+150000*...
SinThirdHarmAngles;
% Finding FFT pitch
magn = abs(fft(Xn, 16384));
OnePointTwo = round(noteFreq * 1.2);
[maxMagn, FFTpitch] = max(magn(1:OnePointTwo));
% Performing DFT grid
LowSpanLimit = 0.8*FFTpitch;
HighSpanLimit = 1.2*FFTpitch;
PartsOfSpan = 1001;
TestFreqs = logspace(log10(LowSpanLimit), log10(HighSpanLimit), PartsOfSpan);
MagnSqrd = ones(1, PartsOfSpan);
for f = 1:PartsOfSpan
Angles = TestFreqs(f)*2*pi/SampFreq*Segm;
XnCos = sum(Xn.*cos(Angles));
XnSin = sum(Xn.*-sin(Angles));
MagnSqrd(f) = XnCos.^2+XnSin.^2;
end
% Finding GRID pitch
[maxMagnSqrd, maxMagnSqrdIndex] = max(MagnSqrd);
GRIDpitch = TestFreqs(maxMagnSqrdIndex);
voiceRatioInterval = GRIDpitch/baseFreq;
% Following should be incorporated in graphics part.
mainUnit = 9/8; % for cents of semitone it is 2
tempUnit = 100; % for cents of semitone it is 1200
noteRatioInterval = noteFreq / baseFreq;
tempNOTEpitch = log(noteRatioInterval)/log(mainUnit)*tempUnit;
tempGRIDpitch = log(voiceRatioInterval)/log(mainUnit)*tempUnit;
% Display results
noteFreq
voicePitch
FFTpitch
GRIDpitch
tempGRIDpitch
tempNOTEpitch