Java 比较字节时,提取的音频样本是否应包含在其原始源中?
假设我有一个音频wav文件,其中有一句话:Java 比较字节时,提取的音频样本是否应包含在其原始源中?,java,audio,javasound,Java,Audio,Javasound,假设我有一个音频wav文件,其中有一句话: +-----------+----------------------------------------+ | meta data | 'Audio recognition sometimes is trick' |.wav +-----------+----------------------------------------+ 现在考虑在AdtuoDista中打开这个音频,并根据它的波形绘制在另一个文件中提取并保存单词“有时”。 +-----
+-----------+----------------------------------------+
| meta data | 'Audio recognition sometimes is trick' |.wav
+-----------+----------------------------------------+
现在考虑在AdtuoDista中打开这个音频,并根据它的波形绘制在另一个文件中提取并保存单词“有时”。
+-----------+-------------+
| meta data | 'sometimes' |.wav
+-----------+-------------+
然后,我使用此Java代码仅从两个文件中获取音频数据:
//...
Path source = Paths.get("source.wav");
Path sample = Paths.get("sometimes.wav");
int index = compare(transform(source), transform(sample));
System.out.println("Shouldn't I be greater than -1!? " + (index > -1));
//...
private int compare(int[] source, int[] sample) throws IOException {
return Collections.indexOfSubList(Arrays.asList(source), Arrays.asList(sample));
}
private int[] transform(Path audio) throws IOException, UnsupportedAudioFileException {
try (AudioInputStream ais = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(Files.readAllBytes(audio)))) {
AudioFormat format = ais.getFormat();
byte[] audioBytes = new byte[(int) (ais.getFrameLength() * format.getFrameSize())];
int nlengthInSamples = audioBytes.length / 2;
int[] audioData = new int[nlengthInSamples];
for (int i = 0; i < nlengthInSamples; i++) {
int LSB = audioBytes[2*i]; /* First byte is LSB (low order) */
int MSB = audioBytes[2*i+1]; /* Second byte is MSB (high order) */
audioData[i] = (MSB << 8) | (255 & LSB);
}
return audioData;
}
}
有人能指出我遗漏了什么吗?@Phil,你就是那个家伙!你的建议让我找到了解决办法
private int compare(byte[] captchaData, byte[] sampleData) throws IOException {
return new String(captchaData).indexOf(new String(sampleData));
}
private byte[] transform(Path audio) throws IOException, UnsupportedAudioFileException {
AudioInputStream ais = AudioSystem.getAudioInputStream(audio.toFile());
AudioFormat format = ais.getFormat();
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
int nBufferSize = 1024 * format.getFrameSize();
byte[] abBuffer = new byte[nBufferSize];
int nBytesRead;
while ((nBytesRead = ais.read(abBuffer)) > -1) {
baos.write(abBuffer, 0, nBytesRead);
}
return baos.toByteArray();
}
}
拆分器:
private List<byte[]> split(byte[] audioData) {
System.out.println(audioData.length);
List<byte[]> byteList = new ArrayList<>();
int zeroCounter = 0;
int lastPos = 0;
for (int i = 0; i < audioData.length; i++) {
if (audioData[i] >= -1 && audioData[i] <= 1) {
zeroCounter++; //too many leading 'zeros' could indicate silence or very low noise...
} else if (zeroCounter > 0) {
if (zeroCounter > 2000) {
int from = lastPos;
int to = i - (zeroCounter/2);
byteList.add(
Arrays.copyOfRange(
audioData,
from,
to));
System.out.println("split from: " + from + " to: " + to);
lastPos = to;
}
zeroCounter = 0;
}
}
return byteList;
}
私有列表拆分(字节[]音频数据){
System.out.println(audioData.length);
List byteList=new ArrayList();
int零计数器=0;
int-lastPos=0;
对于(int i=0;i=-1&&audioData[i]0){
如果(零计数器>2000){
int from=lastPos;
int to=i-(零计数器/2);
byteList.add(
Arrays.copyOfRange(
音频数据,
从…起
),;
System.out.println(“从:“+from+”拆分为:“+to”);
lastPos=to;
}
零计数器=0;
}
}
返回byteList;
}
谢谢 这些是未压缩(PCM)波形吗?另外,你的两个文件的帧大小是多少?我对读取音频文件的方法感到困惑。为什么不使用“AudioInputStream ais=AudioSystem.getAudioInputStream(url);”这假设您传递文件的url而不是路径,无论资源是否在jar内或程序外部,路径都应该起作用。然后,在解码到PCM后进行测试之前,测试并比较字节[]数组。这是我的建议,作为解决问题的第一步,我会做些什么。如果原始文件和Audacity剪辑的格式不同,则生成的PCM肯定也会不同,即使听起来相同。@Phil。实际上,你的第一个建议简化了一些行,谢谢。但是,即使在没有转换的情况下比较字节,我也无法在源音频文件中找到示例。考虑到我已经使用Audacity从源代码中提取了样本,应该保留通道数、速率等等,对吗?即便如此,这里是从AudioInputStream获得的AudioFormat显示的内容:PCM_签名22050.0 Hz,16位,单声道,2字节/帧,小尾端PCM_签名22050.0 Hz,16位,单声道,2字节/帧,小尾端-endian@NPEPCM_签名22050.0 Hz,16位,单声道,2字节/帧,两个文件的小尾端。是的,因此是“第一步”。继续破解“不可能”并回顾剩下的“极不可能的”。从表面上看,人们似乎应该能够找到样品。这里还有另一个想法:搜索从Audacity片段中提取的片段,一些非常小的片段,比如可能只有十几个字节。如果Audacity程序在制作剪辑的过程中对文件进行更改,则最有可能的情况是,它将接近开始或结束,而不是中间。另外,通过从源文件中提取一小段并将其与源文件进行比较来验证比较是否有效。
private List<byte[]> split(byte[] audioData) {
System.out.println(audioData.length);
List<byte[]> byteList = new ArrayList<>();
int zeroCounter = 0;
int lastPos = 0;
for (int i = 0; i < audioData.length; i++) {
if (audioData[i] >= -1 && audioData[i] <= 1) {
zeroCounter++; //too many leading 'zeros' could indicate silence or very low noise...
} else if (zeroCounter > 0) {
if (zeroCounter > 2000) {
int from = lastPos;
int to = i - (zeroCounter/2);
byteList.add(
Arrays.copyOfRange(
audioData,
from,
to));
System.out.println("split from: " + from + " to: " + to);
lastPos = to;
}
zeroCounter = 0;
}
}
return byteList;
}