I am trying to perform hamming followed by FFT of a wav file. I have implemented the same in python. How to do this in Java. I have applied hamming on the given wave file which returns a bytearrayOutputStream. Now how to perform FFT over this byteArrayOutputStream?
I am new to audio processing. My current code is:
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioFFT {
public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
String wavFilePath="C:\\abc.wav";
ByteArrayOutputStream byteArrayOutputStream=applyHamming(wavFilePath);
byte[] bytesOut=byteArrayOutputStream.toByteArray();
System.out.println(Arrays.toString(bytesOut));
}
public static ByteArrayOutputStream applyHamming(String filePath)
{
// TODO Auto-generated method stub
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
File fileIn = new File(filePath);
AudioInputStream audioInputStream;
try {
audioInputStream = AudioSystem.getAudioInputStream(fileIn);
int bytesPerFrame = audioInputStream.getFormat().getFrameSize();
if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) {
bytesPerFrame = 1;
}
int numBytes = 1024 * bytesPerFrame;
byte[] audioBytes = new byte[numBytes];
int numBytesRead = 0;
while ((numBytesRead = audioInputStream.read(audioBytes, 0, audioBytes.length)) != -1) {
outputStream.write(audioBytes, 0, numBytesRead);
}
} catch (UnsupportedAudioFileException | IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return outputStream;
}
private static int BITS_IN_BYTE = 8;
private static AudioInputStream audioInputStream;
private static AudioFormat format;
final static int W = 1024;
public static void getFFT() {
String wavFilePath="C:\\abc.wav";;
File AudioFile = new File(wavFilePath);
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in;
try {
audioInputStream = AudioSystem.getAudioInputStream(AudioFile);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
format = audioInputStream.getFormat();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Error");
}
TargetDataLine line = null;
try {
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
} catch (LineUnavailableException ex) {
System.out.println("Error");
}
line.start();
byte[] data = new byte[W * format.getSampleSizeInBits() / BITS_IN_BYTE];
double[] inbuf = new double[W];
double[] fftbuf = new double[W];
try {
in = new BufferedInputStream(new FileInputStream(AudioFile));
int read;
while ((read = in.read(data)) > 0) {
out.write(data, 0, read);
}
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
data = out.toByteArray();
decode(data, inbuf);
fft(inbuf, fftbuf);
}
public static void decode(byte[] input, double[] output) {
assert input.length == 2 * output.length;
for (int i = 0; i < output.length; i++) {
output[i] = (short) (((0xFF & input[2 * i + 1]) << 8) | (0xFF & input[2 * i]));
output[i] /= Short.MAX_VALUE;
}
}
public static void fft(final double[] inputReal, double[] inputImag) {
assert inputReal.length == 2 * inputImag.length;
int n = inputReal.length;
double ld = Math.log(n) / Math.log(2.0);
if (((int) ld) - ld != 0) {
System.out.println("The number of elements is not a power of 2.");
}
int nu = (int) ld;
int n2 = n / 2;
int nu1 = nu - 1;
double[] xReal = new double[n];
double[] xImag = new double[n];
double tReal, tImag, p, arg, c, s;
double constant;
if (true){
constant = -2 * Math.PI;
}
for (int i = 0; i < n; i++) {
xReal[i] = inputReal[i];
xImag[i] = inputImag[i];
}
int k = 0;
for (int l = 1; l <= nu; l++) {
while (k < n) {
for (int i = 1; i <= n2; i++) {
p = bitreverseReference(k >> nu1, nu);
arg = constant * p / n;
c = Math.cos(arg);
s = Math.sin(arg);
tReal = xReal[k + n2] * c + xImag[k + n2] * s;
tImag = xImag[k + n2] * c - xReal[k + n2] * s;
xReal[k + n2] = xReal[k] - tReal;
xImag[k + n2] = xImag[k] - tImag;
xReal[k] += tReal;
xImag[k] += tImag;
k++;
}
k += n2;
}
k = 0;
nu1--;
n2 /= 2;
}
k = 0;
int r;
while (k < n) {
r = bitreverseReference(k, nu);
if (r > k) {
tReal = xReal[k];
tImag = xImag[k];
xReal[k] = xReal[r];
xImag[k] = xImag[r];
xReal[r] = tReal;
xImag[r] = tImag;
}
k++;
}
double[] newArray = new double[xReal.length * 2];
double radice = 1 / Math.sqrt(n);
for (int i = 0; i < newArray.length; i += 2) {
int i2 = i / 2;
newArray[i] = xReal[i2] * radice;
newArray[i + 1] = xImag[i2] * radice;
}
for (int i = 0; i < newArray.length; i++) {
System.out.println("Array: " + newArray[i]);
}
}
private static int bitreverseReference(int j, int nu) {
int j2;
int j1 = j;
int k = 0;
for (int i = 1; i <= nu; i++) {
j2 = j1 / 2;
k = 2 * k + j1 - 2 * j2;
j1 = j2;
}
return k;
}
}
bytesOut contain your wav file data (after being modified by a Hamming window function). These data
represent the real part that you should send to your fft method (inputReal). For the imaginary part,
create an array of the same size as inputReal and fill it with zeros
//create an array for the imaginary part ( I assume 1024 in length)
double[] imgBytesOut = new double[1024]; //imgBytesOut is not a good name for this
for(int i=0; i<1024;i++)
imgBytesOut[i] = 0;
Now you have everything you need to call fft
fft(bytesOut, imgBytesOut);
Your fft method populates xReal and xImg arrays but since you declared them locally, you won't be
able to use them after fft has finsihed (declare them as static global variables).
Also, if your file contains, say, 10000 samples and your fft size is 1024 samples long(outBytes and imgBytesOut are 1024 samples long)
you will have to call fft repeatedly to process the whole file. To get the best results, you would still need to apply overlapping (e.g. for a 50% overlap and fft size of 1024, you'd process samples 1-1024, then 512-1536, then 1024-2048 and so on).
Related
So i'm trying to implement a parallell version of the Sieve in Java. I'm pretty sure my algorithm is very close to working, it works well for finding all primes up to a small number, (n < 1000 ish) but when the number gets bigger, the sieve finds a small amount of non prime numbers.
An example run with n = 10000000, and the sieve finds 664627 supposed primes numbers, while the actual correct number of primes is 664579. So it marked 48 non-primes as primes. If anyone would be able to take a look at the code below and provide some pointers, that would be greatly appreciated. The code can be compiled and run with Javac Oblig3.java - > java Oblig3 where n is a positive integer and is the max value for n and i is a positive integer and the number of threads to be used.
import java.util.Arrays;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.ReentrantLock;
class Worker implements Runnable {
int n;
int id;
int numOfThreads;
int elementsPerThread;
Oblig3 parent;
int[] primesLessThanRoot;
byte[] oddNumbers;
CyclicBarrier barrier;
ReentrantLock lock;
Worker(int n, int id, int numOfThreads, int[] primesLessThanRoot, Oblig3 parent,
CyclicBarrier barrier,ReentrantLock lock) {
this.n = n;
this.id = id;
this.numOfThreads = numOfThreads;
this.primesLessThanRoot = primesLessThanRoot;
this.elementsPerThread = (int) (primesLessThanRoot.length / numOfThreads);
this.parent = parent;
this.barrier = barrier;
this.lock = lock;
}
private void mark(int num) {
int bitIndex = (num % 16) / 2;
int byteIndex = num / 16;
parent.oddNumbers[byteIndex] |= (1 << bitIndex);
}
#Override
public void run() {
if(id==1){
System.out.println(primesLessThanRoot.length + " " + numOfThreads);
}
int index = id;
while(index < primesLessThanRoot.length){
int count = 3;
int currentNum = primesLessThanRoot[index] * count;
while(currentNum <= n){
if(currentNum % 2 == 1){
mark(currentNum);
// System.out.println("ID: " + id + " marking:" + currentNum + "( " +
primesLessThanRoot[index] + " * " + count + " )");
}
count += 2;
currentNum = primesLessThanRoot[index] * count;
}
index += numOfThreads;
}
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Oblig3 {
int root, n, threads, numOfPrimes;
byte[] oddNumbers;
Long startTime;
Long endTime;
Long totalTime;
Oblig3(int n, int threads) {
this.n = n;
this.threads = threads;
root = (int) Math.sqrt(n);
oddNumbers = new byte[(n / 16) + 1];
}
public static void main(String[] args) {
int n;
int threads;
try {
n = Integer.parseInt(args[0]);
threads = Integer.parseInt(args[1]);
if (threads > Runtime.getRuntime().availableProcessors()) {
System.out.println("More threads than available cores, setting threads to
max available cores");
threads = Runtime.getRuntime().availableProcessors();
}
Oblig3 oblig3 = new Oblig3(n, threads);
oblig3.sieveParallell();
int[] primes = oblig3.getPrimes();
SieveOfEratosthenes soe = new SieveOfEratosthenes(n);
Long soeStart = System.nanoTime();
int[] soePrimes = soe.getPrimes();
Long soeTotal = (System.nanoTime() - soeStart);
System.out.println("Parallell time: " + oblig3.totalTime);
System.out.println("Sequential time: " + soeTotal);
System.out.println(primes.length);
System.out.println(soePrimes.length);
System.out.println(Arrays.equals(primes, soePrimes));
} catch (Exception e) {
e.printStackTrace();
System.out.println("Invalid input");
}
}
void sieveParallell() {
CyclicBarrier barrier;
ReentrantLock lock = new ReentrantLock();
byte[] oddNumbers = new byte[(n / 16) + 1];
startTime = System.nanoTime();
SieveOfEratosthenes soe = new SieveOfEratosthenes((int) Math.sqrt(n));
int[] primesLessThanRoot = soe.getPrimes();
if (primesLessThanRoot.length > threads) {
barrier = new CyclicBarrier(threads + 1);
for (int i = 0; i < threads; i++) {
Worker worker = new Worker(n, i + 1, threads, primesLessThanRoot, this,
barrier, lock);
Thread t = new Thread(worker);
t.start();
}
} else {
barrier = new CyclicBarrier(primesLessThanRoot.length);
for (int i = 0; i < primesLessThanRoot.length - 1; i++) {
Worker worker = new Worker(n, i + 1, threads, primesLessThanRoot, this,
barrier, lock);
Thread t = new Thread(worker);
t.start();
}
}
try {
barrier.await();
endTime = System.nanoTime();
totalTime = endTime - startTime;
} catch (InterruptedException | BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
boolean isPrime(int num) {
int bitIndex = (num % 16) / 2;
int byteIndex = num / 16;
return (oddNumbers[byteIndex] & (1 << bitIndex)) == 0;
}
int[] getPrimes() {
if (n <= 1)
return new int[0];
return collectPrimes();
}
private int[] collectPrimes() {
int start = (root % 2 == 0) ? root + 1 : root + 2;
for (int i = start; i <= n; i += 2)
if (isPrime(i))
numOfPrimes++;
int[] primesWith0 = new int[(int) (numOfPrimes * 1.2)];
primesWith0[0] = 2;
int j = 1;
for (int i = 3; i <= n; i += 2)
if (isPrime(i))
primesWith0[j++] = i;
int count = 0;
for(int num : primesWith0){
if(num != 0){
count ++;
}
}
int [] primes = new int[count];
for(int i = 0; i < count; i++){
primes[i] = primesWith0[i];
}
return primes;
}
static void printPrimes(int[] primes) {
for (int prime : primes)
System.out.println(prime);
}
static boolean isEqual(int[] a, int[] b) {
boolean status = true;
if(a.length == b.length){
for(int i = 0; i < a.length; i++){
if(a[i] != b[i]){
System.out.println(String.format("A[%d]: %d B[%d]: %d", i, a[i], i,
b[i]));
status = false;
}
}
}
else{
if(a.length > b.length){
for (int i = 0; i < b.length; i++) {
if (a[i] != b[i]) {
System.out.println(String.format("A[%d]: %d B[%d]: %d", i, a[i], i,
b[i]));
status = false;
}
}
}
else{
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
System.out.println(String.format("A[%d]: %d B[%d]: %d", i, a[i], i,
b[i]));
status = false;
}
}
}
}
return status;
}
}
I am learning JCuda and studying with JCuda samples.
When I studied a KMeans algorithm code using JCuda, I got a "CUDA_ERROR_ILLEGAL_ADDRESS" when executed line cuCtxSynchronize();
It confused me a lot. How can I solve it?
Here is KMeansKernel.cu
extern "C"
__global__ void add(int n, float *a, float *b, float *sum)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i<n)
{
sum[i] = a[i] + b[i];
}
}
Main method(my class named "CUDA"):
public static void main(String[] args){
// omit some code which input kinds of parameters
try {
// Open image file
BufferedImage bi = ImageIO.read(picFiles);
if (bi == null) {
System.out.println("ERROR: File input error.");
return;
}
// Read image data
int length = bi.getWidth() * bi.getHeight();
int[] imageProperty = new int[length*5];
int[] pixel;
int count = 0;
for (int y = 0; y < bi.getHeight(); y++) {
for (int x = 0; x < bi.getWidth(); x++) {
pixel = bi.getRaster().getPixel(x, y, new int[4]);
imageProperty[count*5 ] = pixel[0];
imageProperty[count*5+1] = pixel[1];
imageProperty[count*5+2] = pixel[2];
imageProperty[count*5+3] = x;
imageProperty[count*5+4] = y;
count++;
}
}
//setup
JCudaDriver.setExceptionsEnabled(true);
// Create the PTX file
String ptxFileName;
try
{
ptxFileName = preparePtxFile("KmeansKernel.cu");
}
catch (IOException e)
{
System.out.println("Warning...");
System.out.println(e.getMessage());
System.out.println("Exiting...");
return;
}
cuInit(0);
CUdevice device = new CUdevice();
cuDeviceGet(device, 0);
CUcontext context = new CUcontext();
cuCtxCreate(context, 0, device);
CUmodule module = new CUmodule();
cuModuleLoad(module, ptxFileName);
CUfunction kmeansFunction = new CUfunction();
System.out.println("x");
cuModuleGetFunction(kmeansFunction, module, "add");
//copy host input to device
CUdeviceptr imageDevice = new CUdeviceptr();
cuMemAlloc(imageDevice, imageProperty.length * Sizeof.INT);
cuMemcpyHtoD(imageDevice, Pointer.to(imageProperty), imageProperty.length * Sizeof.INT);
int blockSizeX = 256;
int gridSizeX = (int) Math.ceil((double)(imageProperty.length / 5) / blockSizeX);
long et = System.currentTimeMillis();
System.out.println(((double)(et-st)/1000.0) + "s");
for (int k = startClusters; k <= endClusters; k++) {
long startTime = System.currentTimeMillis();
int[] clusters = new int[length];
int[] c = new int[k*5];
int h = 0;
for(int i = 0; i < k; i++) {
c[i*5] = imageProperty[h*5];
c[i*5+1] = imageProperty[h*5+1];
c[i*5+2] = imageProperty[h*5+2];
c[i*5+3] = imageProperty[h*5+3];
c[i*5+4] = imageProperty[h*5+4];
h += length / k;
}
double tolerance = 1e-4;
**//got warning in following line
CUDA.KmeansKernel(kmeansFunction, imageDevice, imageProperty, clusters, c, k, tolerance, distanceWeight, colorWeight, blockSizeX, gridSizeX);**
int[] output = calculateAveragePixels(imageProperty, clusters);
BufferedImage outputImage = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < length; i++) {
int rgb = output[i*5];
rgb = (rgb * 256) + output[i*5+1];
rgb = (rgb * 256) + output[i*5+2];
outputImage.setRGB(i%bi.getWidth(), i/bi.getWidth(), rgb);
}
String fileName = (picFiles.getName()) + ".bmp";
File outputFile = new File("output/" + fileName);
ImageIO.write(outputImage, "BMP", outputFile);
long runTime = System.currentTimeMillis() - startTime;
System.out.println("Completed iteration k=" + k + " in " + ((double)runTime/1000.0) + "s");
}
System.out.println("Files saved to " + outputDirectory.getAbsolutePath() + "\\");
cuMemFree(imageDevice);
} catch (IOException e) {
e.printStackTrace();
}
}
Method KmeansKernel:
private static void KmeansKernel(CUfunction kmeansFunction, CUdeviceptr imageDevice, int[] imageProperty, int[] clusters, int[] c,
int k, double tolerance, double distanceWeight, double colorWeight,
int blockSizeX, int gridSizeX) {
CUdeviceptr clustersDevice = new CUdeviceptr();
cuMemAlloc(clustersDevice, clusters.length * Sizeof.INT);
// Alloc device output
CUdeviceptr centroidPixels = new CUdeviceptr();
cuMemAlloc(centroidPixels, k * 5 * Sizeof.INT);
CUdeviceptr errorDevice = new CUdeviceptr();
cuMemAlloc(errorDevice, Sizeof.DOUBLE * clusters.length);
int[] c1 = new int[k*5];
cuMemcpyHtoD(centroidPixels, Pointer.to(c), Sizeof.INT * 5 * k);
// begin algorithm
int[] counts = new int[k];
double old_error, error = Double.MAX_VALUE;
int l = 0;
do {
l++;
old_error = error;
error = 0;
Arrays.fill(counts, 0);
Arrays.fill(c1, 0);
cuMemcpyHtoD(centroidPixels, Pointer.to(c), k * 5 * Sizeof.INT);
Pointer kernelParameters = Pointer.to(
Pointer.to(new int[] {clusters.length}),
Pointer.to(new int[] {k}),
Pointer.to(new double[] {colorWeight}),
Pointer.to(new double[] {distanceWeight}),
Pointer.to(errorDevice),
Pointer.to(imageDevice),
Pointer.to(centroidPixels),
Pointer.to(clustersDevice)
);
cuLaunchKernel(kmeansFunction,
gridSizeX, 1, 1,
blockSizeX, 1, 1,
0, null,
kernelParameters, null
);
**cuCtxSynchronize(); //got warning here.why?**
cuMemcpyDtoH(Pointer.to(clusters), clustersDevice, Sizeof.INT*clusters.length);
for (int i = 0; i < clusters.length; i++) {
int cluster = clusters[i];
counts[cluster]++;
c1[cluster*5] += imageProperty[i*5];
c1[cluster*5+1] += imageProperty[i*5+1];
c1[cluster*5+2] += imageProperty[i*5+2];
c1[cluster*5+3] += imageProperty[i*5+3];
c1[cluster*5+4] += imageProperty[i*5+4];
}
for (int i = 0; i < k; i++) {
if (counts[i] > 0) {
c[i*5] = c1[i*5] / counts[i];
c[i*5+1] = c1[i*5+1] / counts[i];
c[i*5+2] = c1[i*5+2] / counts[i];
c[i*5+3] = c1[i*5+3] / counts[i];
c[i*5+4] = c1[i*5+4] / counts[i];
} else {
c[i*5] = c1[i*5];
c[i*5+1] = c1[i*5+1];
c[i*5+2] = c1[i*5+2];
c[i*5+3] = c1[i*5+3];
c[i*5+4] = c1[i*5+4];
}
}
double[] errors = new double[clusters.length];
cuMemcpyDtoH(Pointer.to(errors), errorDevice, Sizeof.DOUBLE*clusters.length);
error = sumArray(errors);
System.out.println("" + l + " iterations");
} while (Math.abs(old_error - error) > tolerance);
cuMemcpyDtoH(Pointer.to(clusters), clustersDevice, clusters.length * Sizeof.INT);
cuMemFree(errorDevice);
cuMemFree(centroidPixels);
cuMemFree(clustersDevice);
}
Stack trace:
Exception in thread "main" jcuda.CudaException: CUDA_ERROR_ILLEGAL_ADDRESS
at jcuda.driver.JCudaDriver.checkResult(JCudaDriver.java:330)
at jcuda.driver.JCudaDriver.cuCtxSynchronize(JCudaDriver.java:1938)
at com.test.CUDA.KmeansKernel(CUDA.java:269)
at com.test.CUDA.main(CUDA.java:184)
As #talonmies mentions, the kernelParameters you are passing to the cuLaunchKernel method are not in line with add kernel function signature.
You get the error at cuCtxSynchronize because CUDA execution model is asynchronous: cuLaunchKernel returns immediately and actual execution of the kernel on the device is asynchronous. cuCtxSynchronize documentation reads:
Note that this function may also return error codes from previous, asynchronous launches.
The second kernelParameters entry is an int k, where the second parameter of add method is a pointer to float, hence most probably the illegal access error.
I've implemented the Reading wav files in Java in my project (android game) and it works fine.
Now I need to break down the wav file reading into pieces and I don't know what am I doing wrong.
The code runs, and it reads the first part (out of 5), but when trying to read the following parts, the FileInputStream returns -1 and I don't get the logic behind it.
Here's what I have so far:
private List<Float> extractBeats(FileHandle fileHandle) throws Wave.WavFileException, IOException {
List<Float> peaksAppended;
peaksAppended = new ArrayList<Float>();
final FileHandle fileHandleFinal = fileHandle;
for (int i = 0; i < GameSettings.numThreadsAnalyzing; i++) {
final int I = i;
AsyncTask partAnalyzing = new AsyncTask() {
#Override
public List<Float> call() throws Wave.WavFileException, IOException {
final File file = fileHandleFinal.file();
Wave.WavFile wavFile = Wave.WavFile.openWavFile(file);
// Get the number of audio channels in the wav file
final int NUM_CHANNELS = wavFile.getNumChannels();
final int NUM_FRAMES = 1000;
final long totalNumFrames = wavFile.getNumFrames();
final long auxOffset = totalNumFrames / GameSettings.numThreadsAnalyzing;
int offset = (int) auxOffset * I;
if (offset>0){
wavFile.skipFrames(offset);
}
List<Float> peaks;
double[] buffer = new double[NUM_FRAMES * NUM_CHANNELS];
int framesToRead = NUM_FRAMES;
double min = 10;
double max = -10;
// =========================================
// Read file and find out MIN and MAX values
// =========================================
do {
// Read frames into buffer
framesToRead = wavFile.readFrames(buffer, offset, (int) auxOffset, framesToRead);
// Loop through frames and look for minimum and maximum value
for (int s = 0; s < framesToRead * NUM_CHANNELS; s++) {
if (buffer[s] > max) max = buffer[s];
if (buffer[s] < min) min = buffer[s];
}
System.out.println("Buffer_read : " + max + " and min " + min);
}
while (framesToRead != 0);
// Close the wavFile
wavFile.close();
[. . .]//do some other beats extraction stuff
return peaks;
}
};
AsyncExecutor partAnalyzer = new AsyncExecutor(30);
AsyncResult result = partAnalyzer.submit(partAnalyzing);
[. . .]//do some more other beats extraction stuff
}
}
This works fine for the first piece of the song. It reads the first 633000 frames. Now I want it to read the next 633000 frames, but it get stuck into the readSample method.
Here's the sequence running from readFrames method.
public int readFrames(double[] sampleBuffer, int offset, int partSize, int numFramesToRead) throws IOException, WavFileException {
if (ioState != IOState.READING)
throw new IOException("Cannot read from WavFile instance");
for (int f = 0; f < numFramesToRead; f++) {
if (frameCounter == offset + partSize)
return f;
for (int c = 0; c < numChannels; c++) {
sampleBuffer[offset] = floatOffset + (double) readSample() / floatScale;
offset++;
}
frameCounter++;
}
return numFramesToRead;
}
private long readSample() throws IOException, WavFileException {
long val = 0;
for (int b = 0; b < bytesPerSample; b++) {
if (bufferPointer == bytesRead) {
int read = iStream.read(buffer, 0, BUFFER_SIZE);
if (read == -1) throw new WavFileException("Not enough data available");
bytesRead = read;
bufferPointer = 0;
}
int v = buffer[bufferPointer];
if (b < bytesPerSample - 1 || bytesPerSample == 1) v &= 0xFF;
val += v << (b * 8);
bufferPointer++;
}
return val;
}
I tried to use the offset and pass it to the FileInputStream (iStream) but didn't work either. Then, I created the method skipFrames with the following code but also didn't help.
public void skipFrames(int offset){
frameCounter = offset;
}
If solved, I can update the topic with a basic functionallity of the reading wav in pieces, great approach for sound analysis (which it's what I am doing).
Any help would be greatly appreciated.
currently i am trying to perform an FFT on AudioData collected with AudioRecord. My Problem is that every Value is 0 after the FFT. I have no idea why.
I am using the Following code for the FFT (from FFT library in android Sdk). The number of samples is even! (8192)
public class FFT {
int n, m;
// Lookup tables. Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;
public FFT(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 / 2; i++) {
cos[i] = Math.cos(-2 * Math.PI * i / n);
sin[i] = Math.sin(-2 * Math.PI * i / n);
}
}
public void fft(double[] x, double[] y) {
int i, j, k, n1, n2, a;
double c, s, 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;
}
}
}
}
}
This is the code to calculate the Frequency:
private void writeToScreen()
{
while(isRecording)
{
double[] y = new double[bufferSize];
for (int i = 0; i < y.length; i++) {
y[i]=0;
}
double[] x = new double[bufferSize];
//short[] to double[]
for (int i = 0; i < x.length; i++)
{
x[i]= audioBuffer[i]/32768;
}
//perform fft
fft meinfft = new fft(bufferSize);
meinfft.FFT(x, y);
System.out.println("Alle Werte x und y nach FFT:");
for (int i = 0; i < x.length; i++) { //Every Value is 0.0
if(x[i] != 0 || y[i] != 0)
System.out.println("x["+i+"]: "+ x[i] +" y["+i+"]: "+y[i]);
}
System.out.println("Ende Aller Werte");
// calculate index of max Value
int maxIndex =0;
for (int i = 1; i < x.length; i++) {
if(Math.sqrt(x[i]*x[i]+y[i]*y[i]) > Math.sqrt(x[maxIndex]*x[maxIndex]+y[maxIndex]*y[maxIndex]) )
{
maxIndex = i;
}
}
System.out.println("Index des Maximums: "+maxIndex);
double freq = ((1.0 * sampleRate) / (1.0 * bufferSize)) * maxIndex; //Frequency is always 0
System.out.println("wahrscheinliche Frequenz: "+freq);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{}
}
System.out.println("Writethread beendet");
}
Unfortunately i dosn't know very much about FFT. I could imagine that the Transformation from short[] to double[] is wrong or the complete FFT itself. I hope someone can help me.
If you want to try you'll find the complete code below:
import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.LinearLayout;
import android.widget.TextView;
//import android.os.Bundle;
import android.os.Environment;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;
import android.content.Context;
import android.util.Log;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
import de.benediktbock.fft.fft;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import java.io.IOException;
public class MainActivity extends Activity {
private static final String LOG_TAG = "FFTTEST";
private PlayButton mPlayButton = null;
private TextView realTeil = null;
private TextView imgTeil = null;
private fft mFFT = null;
private int channel_config = AudioFormat.CHANNEL_IN_MONO;
private int format = AudioFormat.ENCODING_PCM_16BIT;
private int sampleRate = 8000;
private int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channel_config, format);
private AudioRecord audioInput = null; //new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize);
private short[] audioBuffer = new short[bufferSize];
private Thread readingThread = null,writingThread=null;
private boolean isRecording = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout ll = new LinearLayout(this);
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
realTeil = new TextView(this);
ll.addView(realTeil,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
imgTeil = new TextView(this);
ll.addView(imgTeil,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
realTeil.setText("Realteil");
imgTeil.setText("Imaginärteil");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop");
} else {
setText("Start");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start");
setOnClickListener(clicker);
}
}
private void onPlay(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void startRecording()
{
audioInput = new AudioRecord(AudioSource.MIC, sampleRate, channel_config, format, bufferSize);
audioInput.startRecording();
isRecording = true;
readingThread = new Thread(new Runnable()
{
#Override
public void run()
{
readAudioToBuffer();
}
},"readAudio Thread");
readingThread.start();
writingThread = new Thread(new Runnable()
{
#Override
public void run()
{
writeToScreen();
}
},"write Thread");
writingThread.start();
}
private void writeToScreen()
{
while(isRecording)
{
double[] y = new double[bufferSize];
for (int i = 0; i < y.length; i++) {
y[i]=0;
}
double[] x = new double[bufferSize];
//short[] to double[]
for (int i = 0; i < x.length; i++)
{
x[i]= audioBuffer[i]/32768;
}
//perform fft
fft meinfft = new fft(bufferSize);
meinfft.FFT(x, y);
System.out.println("Alle Werte x und y nach FFT:");
for (int i = 0; i < x.length; i++) { //Every Value is 0.0
if(x[i] != 0 || y[i] != 0)
System.out.println("x["+i+"]: "+ x[i] +" y["+i+"]: "+y[i]);
}
System.out.println("Ende Aller Werte");
// calculate index of max Value
int maxIndex =0;
for (int i = 1; i < x.length; i++) {
if(Math.sqrt(x[i]*x[i]+y[i]*y[i]) > Math.sqrt(x[maxIndex]*x[maxIndex]+y[maxIndex]*y[maxIndex]) )
{
maxIndex = i;
}
}
System.out.println("Index des Maximums: "+maxIndex);
double freq = ((1.0 * sampleRate) / (1.0 * bufferSize)) * maxIndex; //Frequency is always 0
System.out.println("wahrscheinliche Frequenz: "+freq);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{}
}
System.out.println("Writethread beendet");
}
private void readAudioToBuffer()
{
while(isRecording)
{
audioInput.read(audioBuffer, 0,bufferSize);
}
System.out.println("Thread wurde beendet");
}
private void stopRecording()
{
isRecording = false;
audioInput.stop();
audioInput.release();
audioInput= null;
readingThread = null;
}
}
Your inputs are all 0.
short s = 32767;
double d = s/32768;
System.out.println("dividing a short yields a truncated result " + d);
d = (double) s / 32768;
System.out.println("casting to a double and then dividing yields " + d);
I want to make a list of 3 values of the following kind (binary notation!):
0;0;0
1;0;0
0;1;0
11;0;0
10;1;0
.
.
.
1111111111;0;0
0;1111111111;0
0;0;1111111111
and all missing values in between
this list means: all columns have to have all values(permutations?), but only if the bit is not set in another column
this is the problem of putting 10 markable things into 3 different boxes
i tried 3 loops but i always mess it up :(
thats what i have so far:
import java.io.FileNotFoundException;
import java.math.BigInteger;
public class create_referencevalues {
/**
* #param args
*/
public static void main(String[] args) {
Long[] list = { 10L, 40L, 90L, 160L, 250L, 350L, 500L, 650L,800L,1000L };
try {
java.io.PrintStream p = new java.io.PrintStream(
new java.io.BufferedOutputStream(
new java.io.FileOutputStream(new java.io.File(
"C:/users/djdeejay/listall.csv"), false)));
for (Integer i = 0; i < 1024; i++) {
Long sum1 = 0L;
for (Integer j = 0; j < 10; j++) {
if (BigInteger.valueOf(i).testBit(j)) {
sum1 += (list[j]);
}
}
sum1 *= Integer.bitCount(i);
Long sum2 = 0L;
for (int j = 0; j < 10; j++) {
if (BigInteger.valueOf(1023 - i).testBit(j)) {
sum2 += (list[j]);
}
}
sum2 *= 10-Integer.bitCount(i);
p.println(i +";"+ Long.toBinaryString(i)+";" + sum1+";"+ Long.toBinaryString(1023-i)+";"+sum2);
}
p.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
how do i integrate a loop wich gives me the 3rd row and all permutations between the rows ?
thanks for any help
Try this :
public class Permutation {
private static final int NB_DIGITS = 10;
private int[] DIGIT_NUMBER = {1,10,100,1000,10000,100000,1000000,10000000,100000000, 1000000000};
public void dump(PrintStream printStream) {
int[] counter = new int[NB_DIGITS];
Arrays.fill(counter, 0);
do {
int column1 = 0;
int column2 = 0;
int column3 = 0;
for (int i = 0; i < NB_DIGITS; i++) {
int columnIdx = counter[i];
switch (columnIdx) {
case 0 : column1+=DIGIT_NUMBER[i];break;
case 1 : column2+=DIGIT_NUMBER[i];break;
case 2 : column3+=DIGIT_NUMBER[i];break;
default:
assert false;
}
}
printStream.format("%d;%d;%d%n", column1, column2, column3);
} while (increase(counter));
}
public boolean increase(int[] counter) {
int idx = 0;
while (idx < counter.length && counter[idx] == 2) {
counter[idx] = 0;
idx++;
}
if (idx == counter.length) {
return false;
}
counter[idx]++;
return true;
}
public static void main(String[] args) {
new Permutation().dump(System.out);
}
}
The counter array contains the column index where to put your digits. This is actually a loop by hand in base 3 between 0 and 3^10-1 so you reach all the possible positions.
I found this solution:
loop all three rows by all values and mask values you dont want:
if (((k & j) == 0) && ((k & i) == 0) && ((j & i) == 0) && (k^j^i)==max)
that means: a bit at a position must be set only in one row and the rows together must have set all bits
package com.djdeejay.cowTrade.client.standaloneplayer.application;
import java.io.FileNotFoundException;
import java.math.BigInteger;
public class create_referencevalues {
/**
* #param args
*/
public static void main(String[] args) {
Long[] list = { 10L, 40L, 90L, 160L, 250L, 350L, 500L, 650L, 800L,
1000L };
try {
java.io.PrintStream p = new java.io.PrintStream(
new java.io.BufferedOutputStream(
new java.io.FileOutputStream(new java.io.File(
"C:/users/djdeejay/listall.csv"), false)));
Long i = 0l;
Long j = 0l;
Long k = 0l;
Long max = 1023L;
Long count = 0l;
for (i = 0l; i < max; i++) {
for (j = 0l; j < max; j++) {
for (k = 0l; k < max; k++) {
String col1 = Long.toBinaryString(i);
String col2 = Long.toBinaryString(j);
String col3 = Long.toBinaryString(k);
if (((k & j) == 0) && ((k & i) == 0)
&& ((j & i) == 0) && (k^j^i)==max) {
count++;
Long sum1 = 0L, sum2 = 0L, sum3 = 0L;
for (int x = 0; x < 10; x++) {
if (BigInteger.valueOf(i).testBit(x)) {
sum1 += (list[x]);
}
if (BigInteger.valueOf(j).testBit(x)) {
sum2 += (list[x]);
}
if (BigInteger.valueOf(k).testBit(x)) {
sum3 += (list[x]);
}
}
sum1 *= Long.bitCount(i);
sum2 *= Long.bitCount(j);
sum3 *= Long.bitCount(k);
p.println(count + ";" + i + ";" + j + ";" + k);
System.out.println(count + ";" + col1 + ";" + col2 + ";" + col3);
}
}
}
}
System.out.println(count + ";" + i + ";" + j + ";" + k);
p.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}