음성 인식을 위해 원본 오디오 데이터를 한 형식에서 다른 형식으로 변환하려고 시도하고 있습니다. 48Khz, 16-bit stereo signed BigEndian PCM
:Raw PCM 데이터를 RIFF WAV로 변환
- 오디오 포맷은
20ms
청크에 Discord 서버로부터 수신된다. - I는
InputStream
RIFF (little-endian) WAVE audio, 16-bit, mono 16,000Hz
오디오 데이터 길이 3840
와 byte[]
에서 수신되는 오디오 얻어 음성 인식을위한 CMU's Sphinx를 사용하고 있습니다. 이 byte[]
배열은 위에서 설명한 형식 1의 오디오를 20ms
개 포함합니다. 즉,이 오디오의 1 초가 3840 * 50
이고 이는 192,000
입니다. 그래서 초당 192,000
샘플입니다. 이는 바이트가 8 비트이고 우리의 오디오가 16 비트이고 스테레오에 대해 두 번 더하기 때문에 48KHz
샘플 속도, 시간 2 (96K 샘플)입니다. 그래서 48,000 * 2 * 2 = 192,000
. (576,000을
private void addToPacket(byte[] toAdd) {
if(packet.length >= 576000 && !done) {
System.out.println("Processing needs to occur...");
getResult(convertAudio());
packet = null; // reset the packet
return;
}
byte[] newPacket = new byte[packet.length + 3840];
// copy old packet onto new temp array
System.arraycopy(packet, 0, newPacket, 0, packet.length);
// copy toAdd packet onto new temp array
System.arraycopy(toAdd, 0, newPacket, 3840, toAdd.length);
// overwrite the old packet with the newly resized packet
packet = newPacket;
}
이것은 단지 바이트 [] 오디오 데이터 3초 포함될 때까지 하나의 큰 바이트 []에 새로운 패킷을 추가한다 :
그래서 먼저이 방법을 오디오 패킷이 수신 될 때마다 호출 샘플 또는 192000 * 3). 오디오 데이터의 3 초는 사용자가 봇의 활성화 핫 워드 (예 : "컴퓨터")를 말했는지 감지 할 수있는 충분한 시간입니다 (추측).
private byte[] convertAudio() {
// STEP 1 - DROP EVERY OTHER PACKET TO REMOVE STEREO FROM THE AUDIO
byte[] mono = new byte[96000];
for(int i = 0, j = 0; i % 2 == 0 && i < packet.length; i++, j++) {
mono[j] = packet[i];
}
// STEP 2 - DROP EVERY 3RD PACKET TO CONVERT TO 16K HZ Audio
byte[] resampled = new byte[32000];
for(int i = 0, j = 0; i % 3 == 0 && i < mono.length; i++, j++) {
resampled[j] = mono[i];
}
// STEP 3 - CONVERT TO LITTLE ENDIAN
ByteBuffer buffer = ByteBuffer.allocate(resampled.length);
buffer.order(ByteOrder.BIG_ENDIAN);
for(byte b : resampled) {
buffer.put(b);
}
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.rewind();
for(int i = 0; i < resampled.length; i++) {
resampled[i] = buffer.get(i);
}
return resampled;
}
그리고 마지막으로는 시도가 음성을 인식 : 여기에 내가 사운드 데이터를 변환하는 방법은
private void getResult(byte[] toProcess) {
InputStream stream = new ByteArrayInputStream(toProcess);
recognizer.startRecognition(stream);
SpeechResult result;
while ((result = recognizer.getResult()) != null) {
System.out.format("Hypothesis: %s\n", result.getHypothesis());
}
recognizer.stopRecognition();
}
나는 데 문제가 CMUSphinx
충돌 또는 오류 메시지를 제공하지 않는다는 것입니다, 3 초마다 빈 가설이 생깁니다. 나는 정확히 왜 그런지는 모르지만, 내 생각으로는 사운드를 올바르게 변환하지 않았다는 것입니다. 어떤 아이디어? 어떤 도움이라도 대단히 감사하겠습니다.
봐. 디버거에서 실행하십시오. 무슨 일이 일어나는지보십시오. 당신이 다른 모든 가치를 원한다면 왜 나는 하나씩 늘리십니까? 또한 항상 새로운 버퍼를 생성하지 말고 데이터를 복사하면 GC에 엄청난 스트레스가되며 완전히 쓸모가 없습니다. 당신이 원하는 크기의 버퍼 하나, 데이터를 복사해라. –