Я новичок в Java Sound API, много читал в оракуле и Ричарде Браулине и пробую некоторые проекты с его программами. Первое, что я хочу захватить, это звук, понизить его дискретизацию и вернуть обратно в правильный аудиоформат. Тогда я попробую то же самое, но без записи.
Сначала я покажу вам важные части кода, а затем расскажу о своей проблеме:
здесь я записываю звук с микрофона:
stopCapture = false;
try{
int i = 0;
System.out.println("Start");
//Schleife um daten aufzunehmen
while(!stopCapture){
//daten vom targetDataLine lesen
int cnt = targetDataLine.read(tempBuffer,0,tempBuffer.length);
if(cnt > 0){//Jeder 5. Wert wird übernommen
//Die daten in der bytearrayoutputstream speichern
byteArrayOutputStream.write(tempBuffer, 0, cnt);
}
}
Затем я конвертирую byteArrayOutputStream в аудиоданные Bytearray и пытаюсь «понизить дискретизацию» моего записанного звука с частотой дискретизации 48000/5 = 9800. Другими словами, это каждое 5-е значение моего байтового массива audioData. Затем я хочу, чтобы sinc интерполировал его обратно к исходной частоте дискретизации 48000. См. код:
public void run(){
try{
int cnt;
int n = 0;
int k = 0;
int m = 0;
double summe = 0;
ByteArrayOutputStream aufnahme_2 = new ByteArrayOutputStream();
System.out.println("Replay");
//Schleife soll solange laufen bis die letzte Datei abgespielt wurde.
//Am ende gibt die Datei -1 raus
Downsampling 5==> Jeder 5. Wert wird übernommen
for(; m<= audioData.length;m++) {
if ( m%5 < 0.000001 & m != 0) {
k++;
n=k;
}
for(;n<=5+k;n++) {
if(n*5 < audioData.length) {
if(Math.abs((double) m/5-n) <0.00001) {
summe = summe+ audioData[n*5];
}
else {
summe = summe + audioData[n*5]*Math.sin(Math.PI*((double) m/5-n))/( Math.PI*((double) m/5-n)); //Der double cast muss sein, damit die zahl als double und nicht als int gerechnet wird
}
}
}
//byteBuffer.putShort((short) summe);
aufnahme_2.write((short) summe); //Short weil der Datentyp short 2Byte große ist
summe = 0;
n=k;
}
ergebnis = aufnahme_2.toByteArray();
InputStream byteArrayInputStream_down = new ByteArrayInputStream(ergebnis);
audioInputStream = new AudioInputStream(byteArrayInputStream_down, audioFormat,ergebnis.length);
while((cnt = audioInputStream.read(tempBuffer,0,tempBuffer.length))!=-1) {
if(cnt > 0){
sourceDataLine.write(tempBuffer, 0, cnt);
}
}
Мой аудиоформат:
private AudioFormat getAudioFormat(){
float sampleRate = 48000;
int sampleSizeInBits = 16;
int channels = 2;
boolean signed = true;
boolean bigEndian = false;
return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
}
С этим аудиоформатом я получаю очень плохое качество звука. Когда я изменяю sampleSizeInBits в 8, звук становится чище, почему? Я хочу получить разрешение 16 бит. Я попытался сохранить свои значения sinc в целочисленном, байтовом .... формате, и ничего не помогает. Поэтому я надеюсь, что кто-то может помочь и сказать мне, почему это не работает.
PS: Я отправляю изображение, которое я сделал в Matlab, чтобы показать вам мою цель: синяя линия - это мой аудиовход, а черная - реконструированный аудиовыход с пониженной частотой дискретизации.
(short) summe
может не давать полный диапазон возможных значений... - person Jean-Baptiste Yunès   schedule 09.03.2018byte[]
, значит, вы что-то упустили, потому что, когда вы пишетеaudioData[n*5]
, вы записываете не те данные! Если ваш сэмпл 16-битный, вам нужно получить 2 байта:audioData[2*n*5]
иaudioData[2*n*5+1]
, которые в совокупности составляют семпл. - person Jean-Baptiste Yunès   schedule 09.03.2018