В момента работя върху програма за настройка на китара в Java и се опитвам да внедря алгоритъм за хармоничен продуктов спектър, за да определя основната честота.
За момента създадох метод, който намалява моя спектър с фактор f.
Сега се опитвам да умножа всички мои различни спектри с намалена дискретизация заедно. Аз кодирам в java и работя с масиви. Следователно имам масиви за индексите, които са били намалени, и масиви за различните стойности на моя спектър. В момента се опитвам да сложа всички различни масиви с еднакъв размер и да организирам стойностите им, така че да съответстват на правилния индекс с намалена дискретизация. Имам много проблеми с размера и стойностите....
Освен това се опитвам да приложа този алгоритъм въз основа на пример, който имам на лист хартия... Следователно мога да приложа този алгоритъм само с 4 намалени спектъра, но се съмнявам, че това ще е достатъчно, когато всъщност ще използвам истински звуков сигнал .
Ето кода за метода за понижаване на пробите:
import org.jfree.ui.RefineryUtilities;
public class SousEchantillonnage {
public static double[] valuesDownSample(double[] tab, int factor){
int N = tab.length;
double[] values = new double[N];
for (int i = 0; i < N; i++){
values[i] = tab[i];
}
int lengthDownSample = N + (facteur - 1) * (N - 1);
double[] valuesDownSample = new double[lengthDownSample];
for (int i = 0; i < N; i++){
valuesDownSample[i] = values[i];
}
for (int i = N; i < lengthDownSample; i ++){
valuesDownSample[i] = 0;
}
return valuesDownSample;
}
public static double[] indexDownSample(double[] tab, int factor){
int N = tab.length;
double[] indexes = new double[N];
for (int i = 0; i < N; i++){
indexes[i] = i;
}
int lengthDownSample = N + (factor - 1) * (N - 1);
double[] indexDownSample = new double [lengthDownSample];
for (int i = 0; i < lengthDownSample; i++){
indexDownSample[i] = i / factor;
}
return indexDownSample;
}
Този метод изглежда работи.
Ето моя метод за HPS алгоритъма досега:
public static double[] hps(double[] tab){
int N = tab.length;
int factor2 = 2;
int factor3 = 3;
int factor4 = 4;
int lengthDownSample2 = N/2 + (factor2 - 1) * (N/2 - 1);
int lengthDownSample3 = N/2 + (factor3 - 1) * (N/2 - 1);
int lengthDownSample4 = N/2 + (factor4 - 1) * (N/2 - 1);
// Gives us the spectrogram of the signal tab
double[] spectrogram = new double[N];
spectrogramme = FFT.calculFFT(tab);
// We only need the first values of the spectrogram. The other half is the same.
double[] spectrogramCut = new double[N/2];
for (int i = 0; i < N/2; i++){
spectrogramCut[i] = spectrogram[i];
}
// We create the array that contains the values of spectrogramCut that we downsample by a factor 2
double[] valuesSpect2 = new double [sizeDownSamp2];
valuesSpect2 = SousEchantillonnage.valuesDownSample(spectrogramCut, factor2);
// We create an array of the indexes of spectrogramCut that we downsample by a factor 2
double[] indexSpect2 = new double[sizeDownSamp2];
indexSpect2 = SousEchantillonnage.indexDownSample(spectrogramCut, factor2);
// We create the array that contains the values of spectrogramCut that we downsample by a factor 3
double[] valuesSpect3 = new double [sizeDownSamp3];
valuesSpect3 = SousEchantillonnage.valuesDownSample(spectrogramCut, factor3);
// We create an array of the indexes of spectrogramCut that we downsample by a factor 3
double[] indexSpect3 = new double[sizeDownSamp3];
indexSpect3 = SousEchantillonnage.indexDownSample(spectrogramCut, factor3);;
// We create the array that contains the values of spectrogramCut that we downsample by a factor 4
double[] valuesSpect4 = new double [sizeDownSamp4];
valuesSpect4 = SousEchantillonnage.valuesDownSample(spectrogramCut, factor4);
// We create an array of the indexes of spectrogramCut that we downsample by a factor 4
double[] indexSpect4 = new double[sizeDownSamp4];
indexSpect4 = SousEchantillonnage.indexDownSample(spectrogramCut, factor4);
int sizeIndex = N/2 + 5 * (N/2 - 1); // size of the array that contains all the indexes of the downsamples
// We create this array
double[] indexDowSamp = new double[sizeIndex];
indexDowSamp[0] = 0;
indexDowSamp[1] = 0.25;
indexDowSamp[2] = 0.333;
indexDowSamp[3] = 0.5;
indexDowSamp[4] = 0.666;
indexDowSamp[5] = 0.75;
int q = sizeIndex / 6; // quantity of packets of 6 we can do
int r = sizeIndex%6; // what we are left with.
for (int i = 6; i < q * 6; i += 6){
for (int j = 0; j < 6; j++){
indexDowSamp[i + j] = indexDowSamp[i + j - 6] + 1;
}
}
for (int i = 0; i < r; i++){
indexDowSamp[q * 6 + i] = indexDowSamp[q * 6 + i - 6] + 1;
}
Заклещен съм тук. Бих искал да направя метод, който умножава заедно два масива с различна дължина.
По принцип, както можете да видите, когато понижавам дискретизацията на спектрограма, получавам два масива:
- такъв, който има индексите, които са били намалени
- другият, който има стойностите след понижаването.
Това, което бих искал да направя, е да създам масив със същия размер като indexDownSample
: valuesDownSample
. Например имаме indexDownSample[0] = 0
. Бих искал да имам за valuesDownSample[0]
произведението на valuesSpectCut[0] *valuesSpect2[0]*valuesSpect3[0]*valuesSpect4[0]
, защото всички тези масиви имат стойност, която съответства на индекса 0 (indexSpectCut[0] = 0
, indexSpect2[0] = 0 = indexSpect3[0] = indexSpect4[0]
).
за indexDownSample[1]=0.25
, забелязваме, че само indexSpect4[1]= indexDownSample[1] = 0.25
Тогава ще имаме по подразбиране 0 за valuesDownSample[1]
.
И продължаваме така, докато запълним масива.
Ако всичко върви гладко, накрая трябва да имаме:
- valuesDownSample, който съдържа различните стойности на продуктите
- indexDownSample, който съдържа различния индекс с намалена дискретизация.
Просто ще трябва да намеря максималния пик, за да намеря основната си честота.
Единственият ми проблем е, че нямам идея как да направя умножението.....
Ако някой има идея, ще съм много благодарна!