sanji Napisano Wrzesień 18, 2008 Zgłoszenie Share Napisano Wrzesień 18, 2008 Witam wszystkich! Od jakiegoś już czasu męczę się z API ALSy. Znalazłem wiele informacji, ale utknąłęm na podstawach. Ewentualne tutoriale są bardzo pobieżne, pisane na zasadzie: "o tak to np. się robi: (...)", niektóre podstawy są wałkowane wiele razy, a inne traktowane jak oczywiste i pomijane milczeniem. Wiem coś niecoś o cyfrowym dźwięku. Problemem jest dla mnie jednak kwestia komunikacji ze sprzętem. Posłuże się tu działającym przykładem: #include <alsa/asoundlib.h> static char *alsa_device = "default"; snd_pcm_t *h_in; snd_pcm_t *h_out; unsigned short buf[8*512]; int err; int main(void) { // otwarcie urzadzenia err = snd_pcm_open(&h_in, alsa_device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { printf("ERROR (1a): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_open(&h_out, alsa_device, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { printf("ERROR (1b): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } // ustawienie parametrow urzadzenia err = snd_pcm_set_params(h_in, SND_PCM_FORMAT_U16, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 16000, 1, 300000); // ostatni parametr to "latency" if (err < 0) { printf("ERROR (2a): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_set_params(h_out, SND_PCM_FORMAT_U16, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 16000, 1, 300000); // ostatni parametr to "latency" if (err < 0) { printf("ERROR (2b): %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } // pętla kopiująca while(1) { err = snd_pcm_readi (h_in, buf, 8*512); // Kopiowanie z wejścia mikrofonowego if (err == -EPIPE) { puts("ERROR (3a): snd_pcm_prepare\n"); // zapobiega wywalaniu się programu na błędach odczytu z urządzenia snd_pcm_prepare(h_in); } else if (err < 0) { printf("ERROR (3a): %s\n", snd_strerror(err)); } err = snd_pcm_writei(h_out, buf, err); // Zapis do wyjścia głośnikowego if (err < 0) { err = snd_pcm_recover(h_out, err, 0); } if (err < 0) { printf("ERROR (3b): %s\n", snd_strerror(err)); break; } } snd_pcm_close(h_in); snd_pcm_close(h_out); } Teraz czas na pytania: 1) Czym jest to "latency" ustawiane jako ostatni parametr funkcji snd_pcm_set_params()? Na pewno jakieś opóźnienie, tylko pomiędzy czym, a czym? 2) Dlaczego dźwięk jest kopiowany z mikrofonu na głośniki w sposób ciągły, choć funkcje I/O wywoływane są jedna po drugiej, na zmianę, a nie jednocześnie? Na pewno to jakieś banały. Wiem, że funkcje *writei()/*readi() to takie rozszerzone funkcje języka C write() i read(), ale w mojej książce o C tych drugich nie ma, a manual jest krótki i rzeczowy. I ani słowa o tajemniczym latency nie widać ... Nie obrażę się też za jakiś pouczający link. Wszystko dobre, byleby na temat. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Karlik Napisano Wrzesień 18, 2008 Zgłoszenie Share Napisano Wrzesień 18, 2008 Nie znam się na tym API, więc z opóźnieniem nie pomogę, a co do drugiego to po prostu odstęp czasu pomiędzy odczytem a zapisem jest tak mały, że nie zauważasz różnicy i wydaje Ci się to "ciągłe". Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
sanji Napisano Wrzesień 18, 2008 Autor Zgłoszenie Share Napisano Wrzesień 18, 2008 Mi się raczej wydaje, że po zapisie/odczycie całego bufora jednorazowo, karta wysyła kolejne próbki (kierunek zależny od tego czy odczyt, czy zapis) tak długo, jak pozwoli ilość dostępnych danych/wolnego miejsca w buforze. Działa to pewno na zasadzie dorzucania do pieca - tak aby nie zgasł, ale i z uwzględnieniem ograniczonej ilości opału, jaki się w nim jednorazowo zmieści. Problem w tym, że jka na razie nie znalazłem nic, co by potwierdzało na 100%, że tak jest. No i to przeklęte latency, które nie wiadomo, gdzie tu zmieścić. Rozwiązanie które podajesz, bardzo by uzależniało przetwarzanie od dostępnej mocy obliczeniowej. Przy 44.1kHz daje to 23 us (!) na przeładowanie bufora. To 44100 razy mniej, niż trwa cykl napełniania/opróżniania bufora. Po co miałby więc w ogóle istnieć takie coś jak bufor, skoro i tak, o tym, czy muzyka bądzie się przycinać, czy nie, decyduje odstęp poszczególnych próbek od siebie? Zakładając ponadto, że zapis całego bufora trwa dłużej niż zapis jednej próbki, wykorzystanie bufora zamiast zapisu "próbka po próbce", zdaje się dodatkowo jeszcze bardziej zwiększać ilość potrzebnej mocy obliczeniowej o tyle, ile jest próbek w buforze, czyli np. 4096-cio krotnie. Tak więc wydaje mi się, że nie jest tak, jak piszesz, bo to by było szalenie mało wydajne. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Karlik Napisano Wrzesień 18, 2008 Zgłoszenie Share Napisano Wrzesień 18, 2008 Kluczowa jest kwestia tego jak I/O zostało zaimplementowane w samej alsie, nie wiem w jaki sposób korzysta z tego bufora. Niestety nie jestem kompetentny rozwiać Twoje wątpliwości No i pozostaje to, w jaki sposób to sobie kompilator zoptymalizuje. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
menth0l Napisano Wrzesień 19, 2008 Zgłoszenie Share Napisano Wrzesień 19, 2008 Po przeczytaniu tego dochodzę do wniosku, że to "latency" jest to czas jaki karta musi poświęcić na wypełnienie bufora przy zadanym próbkowaniu. Trochę strzelam ale mam nadzieję, że nie mijam się z prawdą Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
sanji Napisano Wrzesień 19, 2008 Autor Zgłoszenie Share Napisano Wrzesień 19, 2008 Teraz jeszcze znaleźć, jaki to ma związek z buforem, liczbą cykli przypadającą na wielkość bufora sprzętu oraz liczbą ramek w cyklu i będzie grało. Okazuje się, że to są ściśle związane ze sobą sprawy, a ich obecność zdaje się wynikać z architektury kart dźwiękowych i tego, czy sterownik i serwer dźwięku potrafią to w pełni wykorzystać. Dziwne jest to, że samo latency, zdaje się wynikać bezpośrednio z wielkości bufora, jednak, czasami działa poprawnie z wartością z palac wyssaną (teoretycznie nie powinno), a czasem wymaga dokładniejszej. Ostatnio znalazłem conieco wyjaśniające linki: http://www.suse.de/~mana/alsa090_howto.html http://linux-muzyka.ixion.pl/tekst.php?id=25084#a -nie dotyczy ALSY, ale na temat. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się