We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello,
I'm writing a program which takes the FFT of various files in a folder and then writes the FFT data to a text file for a machine learning algorithim. However, for many of the files I process, I get zero out for all bands causing me to lose lots of potential data.
I'm also getting the error of "JavaSound Minim Error: Error Reading from File - Stream Closed" on many of the files, though I'm not sure if it affects the FFT data.
Here's my code (I'm new to coding so I'm open to pointers on my code too):
import ddf.minim.analysis.*;
import ddf.minim.*;
import java.io.*;
Minim minim;
AudioPlayer player;
FFT fft;
FileWriter fw;
int counter = 0;
void setup()
{
minim = new Minim(this);
try
{
//create .txt file to record data
fw = new FileWriter("audioRawData.txt");
//run data() which reads .wav files and outputs FFT data to text file
data();
}
catch (IOException e)
{
}
}
void data()
{
try
{
//list files in a directory given by filePath
String filePath = "";
File[] files = new File(filePath).listFiles();
//loop thru files
for(File file : files)
{
//get name of file
String fileName = file.getName();
//only process if .wav file
if (fileName.contains(".wav"))
{
//counter to keep track
counter = counter + 1 ;
//print counter and file name to keep track of what's being processed
println(counter);
println(fileName);
//load file in Minim and play using AudioPlayer
player = minim.loadFile(filePath + fileName);
player.play();
//create new FFT and use Hamming window
fft = new FFT(player.bufferSize(), player.sampleRate());
fft.window(FFT.HAMMING);
//some files might be stereo, so use mix channel
fft.forward(player.mix);
//since all files in the directory are true, write 1 before the FFT data
fw.write("1 ");
//go through FFT using loop
for(int i = 0; i < fft.specSize(); i++)
{
//write FFT with band number in front of it, convert to dB
fw.write((i + 1) + ":" + 20 * log( 2 * fft.getBand(i) / fft.timeSize() ) + " ");
}
//create new line to start next file data on
fw.write("\n");
//close the player to avoid running out of memory
player.close();
}
}
//close and flush writer when done
print("Done Writing!");
fw.close();
fw.flush();
}
catch (IOException e)
{
}
//terminate program when done
exit();
}
Answers
Try this modified example. It loads the wav files in your current data directory, then it traverses the list playing one by one ad saving the processed FFT data in your txt file.
Kf
Thanks for the answer, but some files are still returning zero for the FFT even though there is data in the .wav file. Half of the files I processed using your code still returned zero.
can you post one of the failing files, or a mp3 of it anyway because a wav will be too big.
i have a feeling that you are using fft forward wrongly. you can't just call it once, needs to be once for each frame of the input. normally the draw() loop manages that, but you don't have a draw().
kf's is better because it is looping over the file. but it's doing it in realtime and i wonder if you can do better by not playing the file, just calling forward()
either way i'm getting a file with lots of -Infinity in it 8(
As an exercise, you could check what FFT output gives you zero or infinity and then save that specific buffer into a csv for example. Even better, if you save the buffer and the FFT and then have a look at the data and make some sense of it. If you provide the files, I could do some R or octave magic.
Kf
Hello, thanks for all your responses, but I found a fix by not using the AudioPlayer and instead using the AudioRecordingStream to load my data.
I used this code: https://github.com/ddf/Minim/blob/master/examples/Analysis/offlineAnalysis/offlineAnalysis.pde
I believe that the problem was something to do with the AudioPlayer loading my files wrong, but I'm still not 100% sure why the code didn't work.