Detecting fundamental frequency with comb filter - java

I need to use comb filter/transform to detect fundamental frequency of a wav file in java.
I also needed to implement ZCR, but this was easy.
Now I have this:
int best = 0, best_step = 0;
for (int step = 3; step < 400; ++step) {
int sum = 0;
for (i = 1; i < 10 && i * step < spectrum.length; ++i) {
for (int di = 0; di < i; ++di) {
sum += spectrum[i * step + di] / i;
}
}
sum *= 100;
comb.add(sum);
}
int sum = 0;
for (i = 0; i < comb.size(); ++i) {
sum = comb.get(i); // 3 * comb[i] - comb[i-1] - comb[i+1];
System.out.println(i + " - " + sum);
if (sum > best) {
best_step = i;
best = sum;
}
}
And my problem is that this code detects the wrong frequency. ;( I have searched for an algorithm/implementation (in any language) but have not found anything.
Note, I cannot use autocorelation, etc.. It must be comb filtering.
Edit: A little more explanation of my code:
I load a wav file and put frames to array frames. Then I make fft on it and have array of Complex (named widmo) (simple structure to handle complex numbers).
Now I put abs of Complex numbers into array spectrum:
double[] spectrum = new double[widmo.length];
for (i = 0; i + 1 < widmo.length; ++i) {
spectrum[i] = widmo[i].abs();
}
ArrayList<Integer> comb = new ArrayList<Integer>();
int best = 0, best_step = 0;
for (int step = 3; step < 400; ++step) {
int sum = 0;
for (i = 1; i < 10 && i * step < spectrum.length; ++i) {
for (int di = 0; di < i; ++di) {
sum += spectrum[i * step + di] / i;
}
}
// sum /= step + 100; // ta linijka pozwala usunąć sporo
// niespodziewanych skoków częstotliwości
sum *= 100;
comb.add(sum);
}
int sum = 0;
for (i = 0; i < comb.size(); ++i) {
sum = comb.get(i); // 3 * comb[i] - comb[i-1] - comb[i+1];
// ctx.fillRect(i, canvas.height, 1, -sum);
System.out.println(i + " - " + sum);
// tmp.add(new freqTime(sum,));
if (sum > best) {
best_step = i;
best = sum;
}
}
System.out.println();
System.out.println(best_step);
System.out.println(4 * 44100);
System.out.println((frames.length / numChanels));
System.out.println(best_step * 44100
/ (frames.length / numChanels));
The last println should show me my fundamental frequency, but it doesn't,.
I got this in javascript from my friend.

I figure it out (i think:P). Last println gives basic freq :). Maybe someone will need it or even imporve it :)
ArrayList<double[]> okna = new ArrayList<>();
ArrayList<freqTime> lista = new ArrayList<freqTime>();
int po2 = (int) Math.pow(2,
Integer.parseInt((String) potega2Input.getText()));
po2 /= 2;
double[] triangles = new double[po2];
double maxWykres = 0;
int licznik = 0;
int licznik2 = 0;
int T = frames.length;
boolean wykresFlaga = false;
for (int k = 0; k < T; k += po2) {
licznik = 0;
licznik2 = 0;
double[] tmp = new double[po2];
Complex[] zespolone = new Complex[po2];
for (int i = k; i < k + po2; i++) {
if (i < T) {
tmp[licznik] = frames[i];
zespolone[licznik] = new Complex(frames[i], 0);
licznik2 = licznik;
} else {
tmp[licznik] = frames[licznik2];
zespolone[licznik] = zespolone[licznik2];
}
licznik++;
}
okna.add(tmp);
FFT fft = new FFT();
zespolone = fft.fft(zespolone);
double maxF = 0;
double maxFI = 0;
double maxH = findMaxComp(zespolone);
double[] doWykresu = new double[zespolone.length];
for (int a = 2; a < 100; a++) {
for (int i = 0; i < po2; i++) {
doWykresu[i] = zespolone[i].abs();
triangles[i] = Math.abs(i % (2 * a) - a)
* (maxH) / a;
// triangles[i] = Math.abs(i % (2 * a) - a) * (maxH)
// / a;
}
double sumT = 0;
for (int i = 0; i < po2 / 2; i++) {
sumT += triangles[i] * doWykresu[i];
}
if (sumT > maxF) {
maxF = sumT;
maxFI = a;
}
}
//
// maxFI /= 2;
//
if (wykresFlaga == false) {
maxWykres = maxH;
}
for (int i = 0; i < po2; i++) {
doWykresu[i] = zespolone[i].abs();
triangles[i] = Math.abs(i % (2 * maxFI) - maxFI)
* (maxWykres) / maxFI;
}
if (wykresFlaga == false) {
System.out.println("Max w widmie: " + maxWykres);
new Wykres(doWykresu, 1, triangles);
wykresFlaga = true;
}
// System.out.println((2 * 44100 / po2) * maxFI);
System.out.println((float) (44100 / (float) po2)
* 2*(float) maxFI + " Znalzione a: " + maxFI);
lista.add(new freqTime(
(int) ((float) (44100 / (float) po2) *2* (float) maxFI),
(double) ((double) po2 / 44100)));
/*
* System.out.println((44100 / po2) * maxFI + " " + maxFI +
* " " + maxFI / 44100 + " " + 44100 / (maxFI / po2 * 44100)
* + " " + 44100 * maxFI / T);
*/
// System.out.println(zespolone[(int) maxFI/2].abs());
}

Related

How to write a number as sum of some other numbers' power

Okay firstly I'm sorry I know that I'm not intelligent enough. I'm bad at Math.
I couldn't write an algorithm to this question.
System gives us int x, int y, int boundary and wants us to find which numbers up to boundary satisfy the rule as
some_number = x^i + y^j
Boundary <= 10^6
i and j > = 0
x and y < 100
for example x = 2, y = 3 and boundary= 5,
2 = 2^0 + 3^0
3 = 2^1 + 3^0
4 = 2^0 + 3^1
5 = 2^1 + 3^1
output : 2,3,4,5
import java.util.ArrayList;
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int num = 0;
int remain_x = 0, remain_y = 0;
int count_x = 0, count_y = 0;
if (boundary >= 2) {
res.add(2);
}
for (int i = 3; i <= boundary; ++i) {
if(i == x+y)
res.add(i);
count_x = 0;
count_y = 0;
num = i;
while (num > 0) {
remain_x = num % x;
if (remain_x == 0) {
count_x++;
} else {
while (num > 0) {
remain_y = num % y;
if (remain_y == 0) {
count_y++;
}
num = num / y;
}
}
num = num / x;
}
System.out.println("i =>" +i);
System.out.println("x=>" + count_x);
System.out.println("y =>" + count_y);
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y, boundary );
System.out.println(res);
}
}
Edit:
I wrote something after reading Shark's comment thank you so much. it's working.
import java.util.ArrayList;
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x_k = 0;
int y_k= 0;
while(Math.pow(x,x_k)< boundary){
x_k++;
}
while(Math.pow(y,y_k)< boundary){
y_k++;
}
for(int k = 2 ; k<= boundary;++k) {
for (int i = 0; i < x_k; ++i) {
for (int j = 0; j < y_k; ++j) {
if(k == (int)Math.pow(x,i)+(int)Math.pow(y,j) && !res.contains(k)){
System.out.println("----------------------------------------");
System.out.println(k +" =>" +x + "^" +i +"+"+y+ "^" +j);
res.add(k);
}
}
}
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y,boundary);
System.out.println("x:" + x);
System.out.println("y:" + y);
System.out.println("boundary:" + boundary);
System.out.println("Result:" + res);
}
}
I am not sure if this is the most efficient method. Basically, I increment j until x^i + y^j > boundary then increment i.
public static ArrayList<Integer> findNumbers(int x, int y, int boundary) {
Set<Integer> result = new HashSet<>(); // make sure result is unique
int powerX = 0, powerY = 0, total = 0, tempX = 0;
while (true) {
// calculate x^i
tempX = (int) Math.pow(x, powerX);
while (true) {
// calculate x^i + y^j and compare against boundary
if ((total = tempX + (int) Math.pow(y, powerY)) <= boundary) {
// add result to set and increment y
result.add(total);
powerY++;
// break if y <= 1
if (y <= 1)
break;
} else
break;
}
// break if x <= 1 || x^i > boundary
if (tempX > boundary || x <= 1)
break;
// reset j and increment i
powerY = 0;
powerX++;
}
// return sorted result
ArrayList<Integer> arr = new ArrayList<>();
arr.addAll(result);
arr.sort(null);
return arr;
}
You might be able refactor the code for better efficiency.
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x_k = 0;
int y_k= 0;
while(Math.pow(x,x_k)< boundary){
x_k++;
}
while(Math.pow(y,y_k)< boundary){
y_k++;
}
for(int k = 2 ; k<= boundary;++k) {
for (int i = 0; i < x_k; ++i) {
for (int j = 0; j < y_k; ++j) {
if(k == (int)Math.pow(x,i)+(int)Math.pow(y,j) && !res.contains(k)){
System.out.println("----------------------------------------");
System.out.println(k +" =>" +x + "^" +i +"+"+y+ "^" +j);
res.add(k);
}
}
}
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y,boundary);
System.out.println("x:" + x);
System.out.println("y:" + y);
System.out.println("boundary:" + boundary);
System.out.println("Result:" + res);
}
}

Do-While iteration approach determine by threshold

I have a question using Java do-while loop to determine when to stop by a threshold (MinRevChange in the code).
The larger loop will stop when the value difference between 2 closest data points is below the threshold (DfDi < MinRevChange); and the loop within it will stop when Q is greater than n (30 in this example).
private static int OBMethod33(double mean, double MinRevChange) {
double RmRev = 399;
double BenchPrice = 486;
int n = 30;
int i = 0;
double Fcurr = 0;
double Fopt = 0;
double Fprev = 0;
double DfDi = 999999;
do {
Fcurr = 0;
int Q = 0;
do {
Fcurr = Fcurr
+ RmRev * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q)) * Math.max(Q - i, 0)
+ BenchPrice * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q))
* Math.max(i - Q, 0);
Q++;
} while (Q <= n);
DfDi = Math.abs(Fcurr - Fprev);
Fopt = Fcurr;
Fprev = Fcurr;
i++;
} while ((i <= 10) && (DfDi >= MinRevChange));
return i - 1;
}
private static long factorialRecursive(int i) {
if (i < 0) {
return -1;
}
if (i == 0) {
return 1;
}
if (i < 2)
return i * 1;
return i * factorialRecursive(i - 1);
}
Based on Poisson Distribution pmf function: Poisson Distribution
which is the code (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q))
As Q increases to n, 'Fcurr' will be added for each Q.
DfDi is calculated by deducting the value of two 'i's: 'Fcurr' and 'Fprev'.
The second function returns factorial of a number i! = 1 * 2 * ... * i; used to calculate Poisson Distribution pmf.
Given an example of (mean, MinRevChange) = (6.2, 250) it returns 10;
while I validated the example and function using SAS, it should return 5.
I think within the first function, it seems the 'DfDi >= MinRevChange' condition is not used; How can I modify it? Thanks!
The following code works:
private static int OBMethod33(double mean, double MinRevChange) {
double RmRev = 399;
double BenchPrice = 486;
int n = 30;
int i = 0;
double Fcurr = 0;
double Fopt = 0;
double Fprev = 0;
double DfDi = 999999;
do {
Fcurr = 0;
int Q = 0;
do {
Fcurr = Fcurr
+ RmRev * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q)) * Math.max(Q - i, 0)
+ BenchPrice * (Math.pow(mean, Q) * Math.exp(-mean) / factorialRecursive(Q))
* Math.max(i - Q, 0);
Q++;
} while (Q <= n);
DfDi = Math.abs(Fcurr - Fprev);
Fopt = Fcurr;
Fprev = Fcurr;
i++;
// This line added to print out the result after each iteration;
System.out.println("DfDi = " + DfDi + " :: Fcurr = " + Fcurr);
} while ((i <= 10) && (DfDi >= MinRevChange));
return i - 1;
}
private static long factorialRecursive(int i) {
if (i < 0) {
return -1;
}
if (i == 0) {
return 1;
}
if (i < 2)
return i * 1;
return i * factorialRecursive(i - 1);
It works by setting value pairs of (mean, MinRevChange).
Thanks!

Where does the array get out of boundary in this code?

I'm quite new in Java and I'm getting this error I can manage to understand where it is coming from. Im doing FFT analysis and I'm getting an error:
java.lang.ArrayIndexOutOfBoundsException: 66,
at DrawingFunction.main(DrawingFunction.java:66)
at AnimationGen.begin(AnimationGen.java:54)
at FFTclass.main2(FFTclass.java:213)
at fftTry.main(fftTry.java:34)
the codes are this for the fftTry:
public static void main(String[] args) {
final String NEWLINE = "\n";
String inputFile = "C:/Users/USER/Downloads/DD.wav"; // Place the wav file in the top level directory, ie S:/input.wav
File fileLocation = new File(inputFile);
System.out.println("START");
try {
double[] complexNumber = readFully(fileLocation);
System.out.println(NEWLINE + "Read file");
double[] realPart = complexNumber;
double[] imagPart = new double[realPart.length];
System.out.println("Length = " + realPart.length);
FFTclass FFT = new FFTclass(1024);
FFT.main2(realPart,imagPart,1024);
//for (int i = 0; i < complexNumber.length; ++i) {
// System.out.println(complexNumber[i]);
//}
} catch (Exception ex) {
ex.printStackTrace();
}
}
static double[] readFully(File file) throws UnsupportedAudioFileException, IOException {
AudioInputStream in = AudioSystem.getAudioInputStream(file);
AudioFormat fmt = in.getFormat();
double sampleRate = fmt.getSampleRate();
double frameSize = fmt.getFrameSize();
double auidioDuration = fmt.getFrameRate();
double channels = fmt.getChannels();
System.out.println("File length = " + file.length() + " ");
System.out.println("Sample Rate = " + sampleRate + " per second");
System.out.println("Frame size = " + frameSize + " per second");
System.out.println("Frame rate = " + auidioDuration + " per second");
System.out.println("Channels = " + channels);
System.out.println("Length in time = " + (file.length()/frameSize * auidioDuration) + " seconds");
System.out.println("Length in time in minutes = " + (int)(file.length()/(frameSize* auidioDuration *60)) + " minutes and " + ( (file.length()/(frameSize* auidioDuration *60))- (int)(file.length()/(frameSize* auidioDuration *60)) )* 60 + " seconds");
byte[] bytes;
try {
if (fmt.getEncoding() != Encoding.PCM_SIGNED) {
throw new UnsupportedAudioFileException();
}
// read the data fully
bytes = new byte[in.available()];
in.read(bytes);
} finally {
in.close();
}
int bits = fmt.getSampleSizeInBits();
double max = Math.pow(2, bits - 1);
ByteBuffer bb = ByteBuffer.wrap(bytes);
bb.order(fmt.isBigEndian() ?
ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
double[] samples = new double[bytes.length * 8 / bits];
// convert sample-by-sample to a scale of
// -1.0 <= samples[i] < 1.0
for (int i = 0; i < samples.length; ++i) {
switch (bits) {
case 8:
samples[i] = (bb.get() / max);
break;
case 16:
samples[i] = (bb.getShort() / max);
break;
case 32:
samples[i] = (bb.getInt() / max);
break;
case 64:
samples[i] = (bb.getLong() / max);
break;
default:
throw new UnsupportedAudioFileException();
}
}
return samples;
}
For the FFTclass:
int n, m;
// Lookup tables. Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;
double[] window;
public FFTclass(int n) {
this.n = n;
this.m = (int)(Math.log(n) / Math.log(2));
// Make sure n is a power of 2
if(n != (1<<m))
throw new RuntimeException("FFT length must be power of 2");
// precompute tables
cos = new double[n/2];
sin = new double[n/2];
// for(int i=0; i<n/4; i++) {
// cos[i] = Math.cos(-2*Math.PI*i/n);
// sin[n/4-i] = cos[i];
// cos[n/2-i] = -cos[i];
// sin[n/4+i] = cos[i];
// cos[n/2+i] = -cos[i];
// sin[n*3/4-i] = -cos[i];
// cos[n-i] = cos[i];
// sin[n*3/4+i] = -cos[i];
// }
for(int i=0; i<n/2; i++) {
cos[i] = Math.cos(-2*Math.PI*i/n);
sin[i] = Math.sin(-2*Math.PI*i/n);
}
makeWindow();
}
protected void makeWindow() {
// Make a blackman window:
// w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
window = new double[n];
for(int i = 0; i < window.length; i++)
window[i] = 0.42 - 0.5 * Math.cos(2*Math.PI*i/(n-1))
+ 0.08 * Math.cos(4*Math.PI*i/(n-1));
}
public double[] getWindow() {
return window;
}
/***************************************************************
00089 * fft.c
00090 * Douglas L. Jones
00091 * University of Illinois at Urbana-Champaign
00092 * January 19, 1992
00093 * http://cnx.rice.edu/content/m12016/latest/
00094 *
00095 * fft: in-place radix-2 DIT DFT of a complex input
00096 *
00097 * input:
00098 * n: length of FFT: must be a power of two
00099 * m: n = 2**m
00100 * input/output
00101 * x: double array of length n with real part of data
00102 * y: double array of length n with imag part of data
00103 *
00104 * Permission to copy and use this program is granted
00105 * as long as this header is included.
00106 ****************************************************************/
public void fft(double[] x, double[] y)
{
int i,j,k,n1,n2,a;
double c,s,e,t1,t2;
// Bit-reverse
j = 0;
n2 = n/2;
for (i=1; i < n - 1; i++) {
n1 = n2;
while ( j >= n1 ) {
j = j - n1;
n1 = n1/2;
}
j = j + n1;
if (i < j) {
t1 = x[i];
x[i] = x[j];
x[j] = t1;
t1 = y[i];
y[i] = y[j];
y[j] = t1;
}
}
// FFT
n1 = 0;
n2 = 1;
for (i=0; i < m; i++) {
n1 = n2;
n2 = n2 + n2;
a = 0;
for (j=0; j < n1; j++) {
c = cos[a];
s = sin[a];
a += 1 << (m-i-1);
for (k=j; k < n; k=k+n2) {
t1 = c*x[k+n1] - s*y[k+n1];
t2 = s*x[k+n1] + c*y[k+n1];
x[k+n1] = x[k] - t1;
y[k+n1] = y[k] - t2;
x[k] = x[k] + t1;
y[k] = y[k] + t2;
}
}
}
}
// Test the FFT to make sure it's working
public static void main2(double[] re, double[] im, int N) {
FFTclass fft = new FFTclass(N);
double[] window = fft.getWindow();
double[] ang;
double[] amplitude;
// Impulse
re[0] = 1; im[0] = 0;
for(int i=1; i<N; i++)
re[i] = im[i] = 0;
System.out.println("Impulse");
beforeAfter(fft, re, im);
// Nyquist
for(int i=0; i<N; i++) {
re[i] = Math.pow(-1, i);
im[i] = 0;
}
System.out.println("Nyquist");
beforeAfter(fft, re, im);
// Single sin
for(int i=0; i<N; i++) {
re[i] = Math.cos(2*Math.PI*i / N);
im[i] = 0;
}
System.out.println("Single sin");
beforeAfter(fft, re, im);
// Ramp
for(int i=0; i<N; i++) {
re[i] = i;
im[i] = 0;
}
System.out.println("Ramp");
beforeAfter(fft, re, im);
amplitude = new double[re.length];
ang = new double[re.length];
for(int i=0; i<re.length;i++)
{
amplitude[i] = Math.sqrt( (re[i]*re[i])+ (im[i]*im[i]) );
//Calculate and return the phase
// angle in degrees.
if(im[i] == 0.0 && re[i] == 0.0){ang[i] = 0.0;}
else{ang[i] = Math.atan(im[i]/re[i])*180.0/Math.PI;}
if(re[i] < 0.0 && im[i] == 0.0){ang[i] = 180.0;}
else if(re[i] < 0.0 && im[i] == -0.0){
ang[i] = -180.0;}
else if(re[i] < 0.0 && im[i] > 0.0){
ang[i] += 180.0;}
else if(re[i] < 0.0 && im[i] < 0.0){
ang[i] += -180.0;}
}
for(int i = 100500; i<100600; i++)
{
System.out.print( '\n' + "Magnitude["+i+"] = " +amplitude[i]+ ", ");
System.out.print( '\n' + "Angle phase["+i+"] = " +ang[i]+ ", ");
}
long time = System.currentTimeMillis();
double iter = 30000;
for(int i=0; i<iter; i++)
fft.fft(re,im);
time = System.currentTimeMillis() - time;
System.out.println("\n" + "Averaged " + (time/iter) + "ms per iteration");
System.out.println("Time: " + (time) + "ms");
AnimationGen animation = new AnimationGen();
animation.begin(amplitude);
}
protected static void beforeAfter(FFTclass fft, double[] re, double[] im) {
System.out.println("Before: ");
printReIm(re, im);
fft.fft(re, im);
System.out.println("After: ");
printReIm(re, im);
}
protected static void printReIm(double[] re, double[] im) {
System.out.print("Re: [");
//for(int i=0; i<re.length; i++)
System.out.println("i = " + re.length);
for(int i=100550; i<100650; i++)
System.out.print(((int)(re[i]*1000)/1000.0) + " ");
System.out.print("]\nIm: [");
//for(int i=0; i<im.length; i++)
for(int i=100550; i<100650; i++)
System.out.print(((int)(im[i]*1000)/1000.0) + " ");
System.out.println("]");
}
The AnimationGen:
public int frameWidth = 1920;
public int frameHeigth = 1080;
public int fps = 30;
public void begin(double[] magnitude)
{
int magnitudeLength = magnitude.length;
int value = (int)magnitudeLength/44100;
double [][][] magnitudesPerSecond = new double[value][fps][(int)44100/fps];
for(int i = 0; i < value;i++) {
for(int j = 0; j < fps;j++) {
for (int k = 0; k < (int)44100/fps; k++) {
int arraynumber = k + (j*fps) +(i * (int)44100/fps);
magnitudesPerSecond[i][j][k] = magnitude[arraynumber];
}
}
}
System.out.println("i = " + magnitudesPerSecond.length);
System.out.println("j = " + magnitudesPerSecond[0].length);
System.out.println("k = " + magnitudesPerSecond[0][0].length);
DrawingFunction DF = new DrawingFunction();
DF.main(value, fps, magnitudesPerSecond);
}
And the final DrawingFunction
public int second = 0;
Timer t = new Timer();
TimerTask timeTask = new TimerTask() {
#Override
public void run() {
second++;
}
};
public double addingAngle = 0;
public int frameWidth = 1920;
public int frameHeigth = 1080;
public int value;
public int fps;
public double[][][] magnitude;
double xPoint[][][];
double yPoint[][][];
public void main(int value, int fps, double[][][] magnitude) {
this.value = value;
this.fps = fps;
this.magnitude = magnitude;
///////////////////////////////////////////////////////////////////////////////////////////////////
double xPoint[][][] = new double[value][fps][64];
double yPoint[][][] = new double[value][fps][64];
for (int counter = 0; counter < value; counter++) {
for (int i = 0; i < fps; i++) {
for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {
xPoint[counter][i][j] = magnitude[counter][i][j];
for (int t = 0; t < ((44100 / fps) / 65); t++) { //64 is the number of bands taken into and only 55 from them are used
if(j+t < magnitude[0][0].length) {
xPoint[counter][i][j] += magnitude[counter][i][j + t];
}
System.out.println("Here xPoint[" +i+"]["+j+"]" + (j + t));
}
xPoint[counter][i][j] /= (int) ((44100 / fps) / 64);
}
int t = 0;
for (double angle = addingAngle; angle < 2 * Math.PI + addingAngle; angle += 2 * Math.PI / 55) {
xPoint[counter][i][t] *= Math.cos(angle); //All X points [second][frame][band]
yPoint[counter][i][t] *= Math.sin(angle); //All Y points [second][frame][band]
t++;
}
addingAngle += Math.PI / 110; //110 = 55 points * 2 so rotation is slower
}
this.xPoint = xPoint;
this.yPoint = yPoint;
// Up to here we have 64 xPoints and 64 yPoints, but only the first 55 of each are multiplied by the angle
// jl.setIcon(new ImageIcon("/images/T.png"));
}
for (int i = 0; i < 55; i++) {
System.out.println("Point[" + i + "] is: " + xPoint[0][0][i]);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
JFrame window = new JFrame();
window.add(new DrawingFunction());
window.pack();
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setSize(frameWidth, frameHeigth);
window.setBackground(Color.blue);
window.setVisible(true);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(800, 500, 300, 300); //g.translate(frameWidth/2, frameHeigth/2);
Polygon p = new Polygon();
for (int i = 0; i < 55; i++)
p.addPoint(15 * (int) xPoint[0][0][i], 15 * (int) yPoint[0][0][i]);
g.setColor(Color.black);
g.drawPolygon(p);
g.fillRect(800, 800, 400, 400);
validate(); // So image appears even if screen is small
I know the code is long, hope its not hard to read, its the first time I make a question here
I would look at these lines here:
double xPoint[][][] = new double[value][fps][64];
//...
for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {
xPoint[counter][i][j] = magnitude[counter][i][j];
Note that the inputted fps is 30, so ((44100 / 30) / 64)) = 22.96875 (or 22 as an int). So when this loop iterates, j will be as follows:
j = 0
j = 22
j = 44
j = 66 (Array out of bounds)
The value of fps is 30 (if I'm not missing anything). 44100 / fps = 1,470. So, j goes from 0 to 1,469. But, the third dimension of your array is only 64...
double xPoint[][][] = new double[value][fps][64];
double yPoint[][][] = new double[value][fps][64];
for (int counter = 0; counter < value; counter++) {
for (int i = 0; i < fps; i++) {
for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {
xPoint[counter][i][j] = magnitude[counter][i][j];

string multiplication using a big integer class

I'm trying to write a code that multiplies two strings of integers. I'm not too sure where it's going wrong... It works for some numbers, but is horribly wrong for others. I'm not asking for a full solution, but just a hint (I seriously appreciate any help possible) as to where I'm making the obviously silly mistake. Thanks in advance.
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("Please enter a big integer. ");
String t = scan.nextLine();
System.out.print("And another. ");
String s = scan.nextLine();
BigInt a = new BigInt(t);
BigInt b = new BigInt(s);
System.out.println(a + " + " + b + " = " + a.add(b));
System.out.println(a + " - " + b + " = " + a.sub(b));
System.out.println(a + " * " + b + " = " + a.mul(b));
System.out.println(a + " / " + b + " = " + a.div(b));
}
}
class BigInt {
public BigInt() {
n = new int[1];
}
public BigInt(String s) {
n = new int[s.length()];
for (int i = 0; i < n.length; ++i) {
n[n.length - i - 1] = s.charAt(i) - '0' ;
}
}
private BigInt(int[] n) {
this.n = new int[n.length];
for (int i = 0; i < n.length; ++i) {
this.n[i] = n[i];
}
}
public String toString() {
String s = "";
for (int i : n) {
s = i + s;
}
return s;
}
public BigInt mul(BigInt o) {
int carry = 0;
int s = 0;
int digit;
int subtotal = 0;
int total = 0;
int max = n.length > o.n.length ? n.length : o.n.length;
int[] result = new int[n.length + o.n.length];
for (int i = 0; i < o.n.length; ++i) {
int bottom = i <= o.n.length ? o.n[i] : 0;
for (s = 0; s <= n.length; ++s){
int top = s < n.length ? n[s] : 0;
int prod = (top * bottom + carry);
if (s == (max-1)) {
total = Integer.valueOf((String.valueOf(prod) + String.valueOf(subtotal)));
carry = 0;
digit = 0;
subtotal = 0;
break;
}
if (prod < 10) {
digit = prod;
subtotal += digit;
carry = 0;
}
if (prod >= 10); {
digit = prod % 10;
carry = prod / 10;
subtotal += digit;
}
}
result[i] = total;
}
return new BigInt(trim(result));
}
private int[] trim(int[] nums) {
int size = nums.length;
for (int i = nums.length - 1; i > 0; --i) {
if (nums[i] != 0) {
break;
}
--size;
}
int[] res = new int[size];
for (int i = 0; i < size; ++i) {
res[i] = nums[i];
}
return res;
}
private int[] n;
}
A quick test using:
for (int x = 0; x < 10; x++) {
for (int y = 0; y < 10; y++) {
System.out.println(x + " * " + y + " = " + new BigInt(Integer.toString(x)).mul(new BigInt(Integer.toString(y))));
}
}
demonstrates that somehow your multiply of x * y is actually multiplying by 10x * y. That should give you a clear hint to the problem.

Perlin noise - What am I doing wrong?

I just started with world generation and I've been looking for tutorials on perlin noise everywhere but sadly there are not alot to be found on Google.
The last days I followed a tutorial but I can't get my code to work.
Here is my Java method.
private static double[][] createNoise(int xn, int yn, int sps) {
int m = yn * sps;
int n = xn * sps;
double[][] u = new double[yn + 1][];
double[][] v = new double[yn + 1][];
double[][] x = new double[m][];
double[][] y = new double[m][];
double[][] z = new double[m][];
for (int i = 0; i < m; i++) {
x[i] = new double[n];
y[i] = new double[n];
z[i] = new double[n];
}
for (int i = 0; i < yn + 1; i++) {
u[i] = new double[xn + 1];
v[i] = new double[xn + 1];
}
for (int i = 0; i < xn + 1; i++) {
for (int j = 0; j < yn + 1; j++) {
u[i][j] = nextRandom();
v[i][j] = nextRandom();
}
}
double hx = xn / (n - 1);
double hy = yn / (m - 1);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
x[i][j] = hx * j;
y[i][j] = hy * i;
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int xc = (int)x[i][j];
int yc = (int)y[i][j];
if (x[i][j] % 1 == 0 && x[i][j] != 0 ) xc = xc - 1;
if (y[i][j] % 1 == 0 && y[i][j] != 0 ) yc = yc - 1;
double xr = x[i][j] - xc;
double yr = y[i][j] - yc;
double s11[] = {-xr, -yr};
double s21[] = {-xr, 1 - yr};
double s22[] = {1 - xr, 1 - yr};
double s12[] = {1 - xr, -yr};
double q11 = s11[0] * u[yc][xc] + s11[1] * v[yc][xc];
double q21 = s21[0] * u[yc + 1][xc] + s21[1] * v[yc + 1][xc];
double q22 = s22[0] * u[yc + 1][xc + 1] + s22[1] * v[yc + 1][xc + 1];
double q12 = s12[0] * u[yc][xc + 1] + s12[1] * v[yc][xc + 1];
z[i][j] = lerp(x[i][j], y[i][j], xc, xc + 1, yc, yc + 1, q11, q12, q21, q22);
}
}
return z;
}
The heightmap that the method returns sadly enough looks like this
As you can see, the first row/column is working, but after that the algorithm seems to fail.
I made sure that the method
nextRandom();
returns a float value between -1 & 1.
Thanks alot!
Thanks to user #gawi for pointing this out.
hx = xn / (n - 1);
will divide 2 integers, and most likely return 0.
You can fix this by casting a double to it:
double hx = (double)xn / (n - 1);
Then the map just works!

Categories

Resources