Java实现Shazam声音识别算法的实例代码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java实现Shazam声⾳识别算法的实例代码
Shazam算法采⽤傅⾥叶变换将时域信号转换为频域信号,并获得⾳频指纹,最后匹配指纹契合度来识别⾳频。
1、AudioSystem获取⾳频
奈奎斯特-⾹农采样定理告诉我们,为了能捕获⼈类能听到的声⾳频率,我们的采样速率必须是⼈类听觉范围的两倍。
⼈类能听到的声⾳频率范围⼤约在20Hz到20000Hz之间,所以在录制⾳频的时候采样率⼤多是44100Hz。
这是⼤多数标准MPEG-1的采样率。
44100这个值最初来源于索尼,因为它可以允许⾳频在修改过的视频设备上以25帧(PAL)或者30帧( NTSC)每秒进⾏录制,⽽且也覆盖了专业录⾳设备的20000Hz带宽。
所以当你在选择录⾳的频率时,选择44100Hz就好了。
定义⾳频格式:
public static float sampleRate = 44100;
public static int sampleSizeInBits = 16;
public static int channels = 2; // double
public static boolean signed = true; // Indicates whether the data is signed or unsigned
public static boolean bigEndian = true; // Indicates whether the audio data is stored in big-endian or little-endian order
public AudioFormat getFormat() {
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,
bigEndian);
}
调⽤麦克风获取⾳频,保存到out中
public static ByteArrayOutputStream out = new ByteArrayOutputStream();1
try {
AudioFormat format = smartAuto.getFormat(); // Fill AudioFormat with the settings
info = new (TargetDataLine.class, format);
startTime = new Date().getTime();
System.out.println(startTime);
SmartAuto.line = (TargetDataLine) AudioSystem.getLine(info);
SmartAuto.line.open(format);
SmartAuto.line.start();
new FileAnalysis().getDataToOut("");
while (smartAuto.running) {
checkTime(startTime);
}
SmartAuto.line.stop();
SmartAuto.line.close();
} catch (Throwable e) {
e.printStackTrace();
}
获取到的out数据需要通过傅⾥叶变换,从时域信号转换为频域信号。
傅⾥叶变换
public Complex[] fft(Complex[] x) {
int n = x.length;
// 因为exp(-2i*n*PI)=1,n=1时递归原点
if (n == 1){
return x;
}
// 如果信号数为奇数,使⽤dft计算
if (n % 2 != 0) {
return dft(x);
}
// 提取下标为偶数的原始信号值进⾏递归fft计算
Complex[] even = new Complex[n / 2];
for (int k = 0; k < n / 2; k++) {
even[k] = x[2 * k];
}
Complex[] evenValue = fft(even);
// 提取下标为奇数的原始信号值进⾏fft计算
// 节约内存
Complex[] odd = even;
for (int k = 0; k < n / 2; k++) {
odd[k] = x[2 * k + 1];
}
Complex[] oddValue = fft(odd);
// 偶数+奇数
Complex[] result = new Complex[n];
for (int k = 0; k < n / 2; k++) {
// 使⽤欧拉公式e^(-i*2pi*k/N) = cos(-2pi*k/N) + i*sin(-2pi*k/N)
double p = -2 * k * Math.PI / n;
Complex m = new Complex(Math.cos(p), Math.sin(p));
result[k] = evenValue[k].add(m.multiply(oddValue[k]));
// exp(-2*(k+n/2)*PI/n) 相当于 -exp(-2*k*PI/n),其中exp(-n*PI)=-1(欧拉公式);
result[k + n / 2] = evenValue[k].subtract(m.multiply(oddValue[k]));
}
return result;
}
计算out的频域值
private void setFFTResult(){
byte audio[] = SmartAuto.out.toByteArray();
final int totalSize = audio.length;
System.out.println("totalSize = " + totalSize);
int chenkSize = 4;
int amountPossible = totalSize/chenkSize;
//When turning into frequency domain we'll need complex numbers:
SmartAuto.results = new Complex[amountPossible][];
DftOperate dfaOperate = new DftOperate();
//For all the chunks:
for(int times = 0;times < amountPossible; times++) {
Complex[] complex = new Complex[chenkSize];
for(int i = 0;i < chenkSize;i++) {
//Put the time domain data into a complex number with imaginary part as 0:
complex[i] = new Complex(audio[(times*chenkSize)+i], 0);
}
//Perform FFT analysis on the chunk:
SmartAuto.results[times] = dfaOperate.fft(complex);
}
System.out.println("results = " + SmartAuto.results.toString());
}
总结
以上所述是⼩编给⼤家介绍的Java实现Shazam声⾳识别算法的实例代码,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。
在此也⾮常感谢⼤家对⽹站的⽀持!。