如何将汉宁函数应用于我的音频样本?
How do I apply the hanning function to my audio sample?
我是大学生。我正在为我的最后一年项目开发一个音乐识别系统。根据 "Robust Audio Fingerprint Extraction Algorithm Based on 2-D Chroma" 研究论文,我的系统中应该包含以下功能。
捕获音频信号----> 成帧Window(汉宁window)-----> FFT ----->
高通滤波器 -----> 等......
我能够为音频捕获功能编写代码,并且我也将 FFT API 应用于代码。但是我对如何将 hanning window 函数应用于我的代码感到困惑。有人可以帮我做这个功能吗?告诉我这个功能需要在什么地方添加,需要怎么添加到代码中。
这是我的音频捕获代码和应用 FFT 代码:
private class RecordAudio extends AsyncTask<Void, double[], Void> {
@Override
protected Void doInBackground(Void... params) {
started = true;
try {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(
recordingFile)));
int bufferSize = AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
frequency, channelConfiguration, audioEncoding,
bufferSize);
short[] buffer = new short[blockSize];
double[] toTransform = new double[blockSize];
long t = System.currentTimeMillis();
long end = t + 15000;
audioRecord.startRecording();
double[] w = new double[blockSize];
while (started && System.currentTimeMillis() < end) {
int bufferReadResult = audioRecord.read(buffer, 0,
blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
toTransform[i] = (double) buffer[i] / 32768.0;
dos.writeShort(buffer[i]);
}
// new part
toTransform = hanning (toTransform);
transformer.ft(toTransform);
publishProgress(toTransform);
}
audioRecord.stop();
dos.close();
} catch (Throwable t) {
Log.e("AudioRecord", "Recording Failed");
}
return null;
}
这些链接提供了 hanning window 算法和代码片段:
我使用以下代码将 hanning 函数应用于我的应用程序并且它适用于我....
public double[] hanningWindow(double[] recordedData) {
// iterate until the last line of the data buffer
for (int n = 1; n < recordedData.length; n++) {
// reduce unnecessarily performed frequency part of each and every frequency
recordedData[n] *= 0.5 * (1 - Math.cos((2 * Math.PI * n)
/ (recordedData.length - 1)));
}
// return modified buffer to the FFT function
return recordedData;
}
起初,我认为您应该考虑固定 FFT 长度。如果我正确理解您的代码,您现在正在使用某种最小缓冲区大小也作为 FFT 长度。 FFT 长度对计算的性能和分辨率有巨大影响。
您的 link 到 WindowFunction.java 可以为您生成一个数组,该数组的长度应与您的 FFT 长度相同(我认为在您的情况下为 blockSize)。然后,您应该将缓冲区的每个样本与数组中具有相同 id 的 WindowFunction 返回的值相乘。
这应该在 FFT 之前完成。
我是大学生。我正在为我的最后一年项目开发一个音乐识别系统。根据 "Robust Audio Fingerprint Extraction Algorithm Based on 2-D Chroma" 研究论文,我的系统中应该包含以下功能。
捕获音频信号----> 成帧Window(汉宁window)-----> FFT ----->
高通滤波器 -----> 等......
我能够为音频捕获功能编写代码,并且我也将 FFT API 应用于代码。但是我对如何将 hanning window 函数应用于我的代码感到困惑。有人可以帮我做这个功能吗?告诉我这个功能需要在什么地方添加,需要怎么添加到代码中。
这是我的音频捕获代码和应用 FFT 代码:
private class RecordAudio extends AsyncTask<Void, double[], Void> {
@Override
protected Void doInBackground(Void... params) {
started = true;
try {
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(
recordingFile)));
int bufferSize = AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
frequency, channelConfiguration, audioEncoding,
bufferSize);
short[] buffer = new short[blockSize];
double[] toTransform = new double[blockSize];
long t = System.currentTimeMillis();
long end = t + 15000;
audioRecord.startRecording();
double[] w = new double[blockSize];
while (started && System.currentTimeMillis() < end) {
int bufferReadResult = audioRecord.read(buffer, 0,
blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
toTransform[i] = (double) buffer[i] / 32768.0;
dos.writeShort(buffer[i]);
}
// new part
toTransform = hanning (toTransform);
transformer.ft(toTransform);
publishProgress(toTransform);
}
audioRecord.stop();
dos.close();
} catch (Throwable t) {
Log.e("AudioRecord", "Recording Failed");
}
return null;
}
这些链接提供了 hanning window 算法和代码片段:
我使用以下代码将 hanning 函数应用于我的应用程序并且它适用于我....
public double[] hanningWindow(double[] recordedData) {
// iterate until the last line of the data buffer
for (int n = 1; n < recordedData.length; n++) {
// reduce unnecessarily performed frequency part of each and every frequency
recordedData[n] *= 0.5 * (1 - Math.cos((2 * Math.PI * n)
/ (recordedData.length - 1)));
}
// return modified buffer to the FFT function
return recordedData;
}
起初,我认为您应该考虑固定 FFT 长度。如果我正确理解您的代码,您现在正在使用某种最小缓冲区大小也作为 FFT 长度。 FFT 长度对计算的性能和分辨率有巨大影响。
您的 link 到 WindowFunction.java 可以为您生成一个数组,该数组的长度应与您的 FFT 长度相同(我认为在您的情况下为 blockSize)。然后,您应该将缓冲区的每个样本与数组中具有相同 id 的 WindowFunction 返回的值相乘。
这应该在 FFT 之前完成。