Czy Java obsługuje audio z częstotliwością próbkowania 384 kHz?

0

Witam, mam problem w kwestii pobierania danych z wejścia audio. Chciałbym osiągnąć częstotliwość próbkowania na poziomie 384 kHz, jako że używam wejścia audio do nietypowych zastosowań wymagających dużej dokładności w próbkowaniu. Mam taki kod:

[...]
final static AudioFormat format = new AudioFormat(48000, 8, 1, true, true);
[...]
TargetDataLine line;
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
line=(TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();
ByteArrayOutputStream out  = new ByteArrayOutputStream();
int numBytesRead;
byte[] data = new byte[16040];
numBytesRead =  line.read(data, 0, data.length);
[...]

Póki co, używam częstotliwości próbkowania 48 kHz, chciałbym jednak przenieść się na 384 kHz, a mogę uzyskać maksymalnie 200 kHz. Wszystko powyżej tej wartości zwraca błąd, że nie jest ona obsługiwana; mimo że moja karta dźwiękowa w pełni obsługuje aż 384 kHz. Pytanie więc, czy to Java nie obsługuje nic powyżej 200 kHz, czy może robię coś źle i da się to obejść żeby w pełni wykorzystać możliwości karty dźwiękowej. Z góry dzięki za odpowiedź.

0

Podaj stacktrace.

0

Błąd z prostego programu testującego odczytywanie danych, z linijkami kodu identycznymi do tych z mojego pierwszego postu:

Exception in thread "main" javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 384000.0 Hz, 8 bit, mono, 1 bytes/frame, not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:513)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:121)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:153)
at testaudio.Testaudio.main(Testaudio.java:29)
C:\Users\Kacper\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml Java returned: 1
BUILD FAILED (total time: 0 seconds)

Linia 29:
line.open(format);

O ile o to chodziło.

1

Hmm, trochę pogrzebałem i wychodzi na to, że line.open wchodzi do com.sun.media.sound.DirectAudioDevice#nOpen, które jest już natywne i ciężko śledzić co się w środku dzieje.

Na twoim miejscu spróbowałbym wyciągnąć z Javy listę wspieranych formatów lub w pętli sprawdzałbym różne kombinacje parametrów dla AudioFormat aż do skutku.

0

musisz mieć kartę, która obsługuje taką częstotliwość próbkowania. Standard (większość wbudowanych w płytę) to 44kHz, lepsze mają 96kHz ale to wyjście czyli przetwornik C/A. Natomiast kart z przetowornikiem A/C powyżej 96kHz nie udało mi się znaleźć w google. Pewnie dedykowany zewnętrzny przetwornik byś znalazł ale cena by pewnie była jak za niezły samochód.

0

Spróbowałem wyciągnąć listę wspieranych formatów i wyszło mi coś takiego:
"[PCM_UNSIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, , PCM_SIGNED unknown sample rate, 8 bit, mono, 1 bytes/frame, ,[...]"
Nie zawiera to informacji o wspieranych częstotliwościach próbkowania. Próbowałem z różnymi formatami (np. 16 bitowy, 32 bitowy, mono, stereo) i nie udało się osiągnąć sukcesu. Cóż, jak ktoś ma jeszcze jakiś pomysł to proszę o pomoc.
Natomiast podstawowe pytanie: czy Java w ogóle wspiera chcianą przeze mnie częstotliwość próbkowania?

UP: mam kartę zgodną z Realtek High Definition Audio, które według specyfikacji wspiera 384 kHz częstotliwości próbkowania. Ale może jest tu jakiś błąd w moim rozumowaniu.

0

podaj model karty

0

Model karty to:
Intel 82801GB ICH7

Chyba gafę popełniłem bo jeszcze raz zajrzałem do dokumentacji High Definition Audio i napisane tam jest o wsparciu 192 kHz, natomiast już nie o 384 kHz, co może wyjaśniać fakt, że nie mogę osiągnąć częstotliwości wyższej od 200 kHz (zapewne producent dał dodatkową rezerwę powiększającą wspieraną częstotliwość o 8 kHz):

Sample rate support ranging from 6 kHz to 192 kHz

Mam natomiast inne pytanie. Co jeśli chcę wyciągnąć z wejścia audio 2-bajtowe dane zamiast 1-bajtowych, lub gdy chcę wyciągnąć dane z dwóch kanałów? Jak one się wtedy układają w tablicy bajtów?

0

za http://www.realtek.com.tw/products/productsView.aspx?Conn=4&Langid=1&Level=5&PFid=28&ProdID=44

All DACs support 44.1k/48k/96k/192kHz sample rate
All ADCs support 44.1k/48k/96kHz sample rate

jak widzisz przetworniki A/C mają max 96kHz

0

Jak one się wtedy układają w tablicy bajtów?

Na pewno zależy to od tzw endianess, które może być big endian, little endian lub mixed endian (ale to przy 32-bitach dopiero).

Z tego co widziałem to API Javowe pozwala chyba wczytać WAVy nieskompresowane, więc ogarnij format takiego pliku, wpisz tam bajty 1, 2, 3, 4, 5 itd w miejsce danych dźwiękowych, a potem wczytaj w Javie i podejrzyj co tam wyszło w strumieniach :]

0

@Wibowit
Dzięki, ogarnąłem już że bajty układają się tak, że np. jeśli zapisują się do tablicy dwa bajty i mamy tablicę 16 000 bajtów to wartość pierwszego bajta jest w numerze [0], a druga w numerze [8000] i trzeba je pomnożyć i wyjdzie wynik odczytu.

@abrakadaber
Dzięki za źródło. Przeanalizowałem metodę nagrywania dźwięku za pomocą programu Audacity - połączyłem kablem wejście audio z wyjściem audio tak, żeby odtwarzany z komputera dźwięk się nagrał, włączyłem dźwięk i nagrywanie i odkryłem jedną rzecz. Mianowicie przy użyciu nagrywania z częstotliwością 384 kHz sygnał był co prawda nagrany z mniejszą dynamiką (96 kHz), ale ani nie wywaliło błędu, ani nie było widać "zębów", sample były ładnie zaokrąglone. I chciałbym coś takiego uzyskać w moim programie pisanym w Javie. Tak więc ponownie wraca temat ograniczenia do 200 kHz. Zależy mi na wyższej częstotliwości próbkowania ze względu na to, że potrzebuję móc na podstawie odczytanych sampli obliczyć wartość modulacji częstotliwości, a do tego potrzebna jest jak największa gęstość próbek na sekundę.

1

trzeba je pomnożyć i wyjdzie wynik odczytu.

Skąd ci wyszło, że trzeba pomnożyć? Jeśli chcesz z dwóch bajtów złożyć wartość 16-bitową to powinieneś raczej zastosować przesunięcia bitowe, np:
```word = (hibyte << 8) + lobyte``

Poza tym zmianę częstotliwości próbkowania można przeprowadzić programowo. Jakości to nie doda (co najwyżej stracimy), ale jeśli nie poradzisz sobie z oryginalną to możesz sobie jakimś gotowcem przekonwertować. Wyguglaj "java resampling".

0

Witam ponownie po dłuższym czasie. Z programu nie zrezygnowałem, a wręcz udoskonaliłem jego technikę działania, tak aby dokładniej wykorzystywał dane na wejściu. Mimo wszystko i tak więcej bym osiągnął mając wyższą częstotliwość próbkowania. Specyfika programu sprawia, że sztuczny resampling nie poprawia odczytu, tu potrzebne jest fizyczne zwiększenie gęstości próbek. Zastanawia mnie czy wirtualna maszyna Javy w ogóle obsługuje chcianą przeze mnie częstotliwość próbkowania; bo jak tak, to może pomoże zmiana z domyślnej biblioteki Javy na jakąś inną. Macie jakieś sugestie co do wyboru biblioteki? Nacisk kładę na prostotę odczytu surowych danych z wejścia, bo właściwie to na razie jedyna rzecz którą ma ta biblioteka w moim programie robić. Z góry dzięki a odpowiedź.

@Wibowit
Dzięki za odpowiedź, przesunięcia bitowe to jednak lepsze rozwiązanie niż moje

1 użytkowników online, w tym zalogowanych: 0, gości: 1