Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

Analiza pisków, czyli jak zrobić zdalnie selfie

W moim ulubionym niemieckim sklepie w którym zaopatruję się w życiodajne składniki pokarmowe czasami trafiają się dziwne produkty nieznanych szerzej wewnętrznych marek. Skuszony sekcją z obniżkami cen zakupiłem sobie zdalny wyzwalacz do selfie. Nie, żebym specjalnie zamierzał robić selfie, bo ich nie robię, ale mam w głowie pewien projekt, do którego zdalny wyzwalacz mógłby być użyteczny.

Niestety, zaślepiła mnie przecena. "Selfie Remote Control Release" firmy SilverCrest na opakowaniu miał owszem wspomnianą kompatybilność z Androidem i iOS, którą zignorowałem, bo przecież i tak do mojego Windows w jakiś sposób go podłączę. Z tyłu opakowania miał wspomniane, że działa na zasięgu do 8 metrów, że ma bezpłatną aplikację, że może wyzwolić kilka telefonów z zasięgu.

I to ostatnie zdanie spowodowało, że podniosłem brwi. Ale jak to przycisk udający klawiaturę BT miałby się sparować z kilkoma telefonami naraz? Dziwne. Kiedy w domu rozpakowałem gadżet coś mnie tknęło. Na opakowaniu nie było ani słowa o Bluetooth. Ani w instrukcji. To urządzenie nie działało w oparciu o tę technologię. Zatem więc jak?

Nacisnąłem więc przycisk (jeden z dwóch) dostępnych na tym czymś, a on wydał z siebie pisk. Najpierw dość zwykły, a potem wysoki ćwierk. Dziwaczne. Odpowiednią aplikację pobrałem na leżącego w domu Nexusa 4 z Androidem 5 na którym czasami coś testuję. I nacisnąłem przycisk, a on zrobił zdjęcie. Łał. Nie, serio. Mamy urządzenie, które piszczy, a telefon na to piszczenie reaguje zrobieniem zdjęcia. I to (po testach) wychodzi na to, że "słyszy" ten pisk całkiem nieźle.

Pozostawało pytanie - co to za pisk i jak on działa?

Zacząłem od próby dekompilacji aplikacji dla Androida. Zawiera ona dużo śmieci, w zasadzie jest prostą aplikacją do robienia zdjęć (i wrzucania ich na Facebooka), ale najbardziej interesująca wydawała się klasa o nazwie Detector w pakiecie com.magcom.pitchdetector. Zobaczenie jej zawartości nie przyniosło jednak rozwiązania:

public class Detector { static { System.loadLibrary("detector"); } /* (...) */ private static native int apiDetect(byte[] bArr, int i); private static native void apiInit(Object obj, int[] iArr, int[] iArr2, int i, int i2, int i3, int i4, int i5, int i6, int i7); private static native void apiTerminate(); }

Aha, native. W lib/armeabi-v7a/ znajdowała się za to biblioteka libdetector.so. Czyli całe wykrywanie robi natywna biblioteka w języku C, a dekompilacja czegoś takiego to już trudniejsza sprawa. Ale sama nazwa - pitch detector - sugeruje wykrywanie określonego tonu (a magcom.com sugeruje oryginalnego chińskiego producenta dla tego gadżetu).

Urządzenie ma dwa przyciski - jeden powoduje zrobienie zdjęcia, a drugi - zmianę aparatu używanego w aplikacji. Jeden powoduje jeden pisk i wysoki dźwięk, a drugi dwa piski i wysoki dźwięk. Strzeliłem zatem, że ten wysoki dźwięk zapewne koduje w swojej częstotliwości za jaką funkcję odpowiada.

Sprawa wydawała się prosta. Wkładane mi przez lata studiów całki zaczęły się kłębić w głowie, w której powstała myśl w postaci użycia Dyskretnej Transformaty Fouriera. DFT przerabia sygnał z dziedziny czasu na dziedzinę częstotliwości. Istnieje szansa, że pisk będzie dość jednorodny i będzie wysokim "pikiem" na wykresie. Pozostało nagrać brelok, wykonać transformatę i zobaczyć, co się stanie.

Nagrałem do pliku WAV, znalazłem odpowiedni fragment kodu w Pythonie, wyrysowałem transformatę z użyciem znalezionego w Internecie fragmentu kodu. Wygenerowany wykres wyglądał następująco:

Jak widać, największy "pik" jest przy około 25 kHz. Ale coś z tą wartością jest nie tak. Nagrywałem dźwięk z próbkowaniem 44,1 kHz. Niemożliwe jest w takim przypadku poprawne uzyskanie dźwięku o częstotliwości powyżej 22,05 kHz (częstotliwość Nyquista). Sięgnąłem więc po inną metodę, uświadamiając sobie, że przecież Audacity, którym nagrywam, również posiada funkcję wyrysowania widma.

Widmo częstotliwościowe dla całego dźwięku było niestety dość "brzydkie", odbiegało od mojej wizji pięknego czystego piku. Spójrzmy jednak na spektrogram sygnału (włączenie spektrogramu w Audacity zajęło mi kilka dłuższych chwil, tak nawiasem):

A zwłaszcza na wyższe częstotliwości:

Wyraźnie widać trwające 0,25 sekundy "coś", a potem drugie "coś", mniej więcej tak samo długie. Analiza częstotliwościowa pierwszego fragmentu wykazuje wyraźny pik na 15876 Hz, a drugiego na 15595 Hz. Czyżby to to?

Spróbujmy zatem zasymulować telefonowi odtworzenie tego dźwięku (i liczmy na to, że głośnik potrafi z siebie wydać taki odgłos).

Chwila pełna napięcia...

Działa! Zrobił zdjęcie (widać odpowiednie ikonki na ekranie aplikacji na telefonie). Kolejne zabawy jednak przyniosły gorszy wniosek - on nie opiera się tylko na wykrywaniu określonych częstotliwości, ale również na ich czasie trwania. I chyba na większej liczbie częstotliwości, bo wycięcie sporej części z nich filtrem górnoprzepustowym spowodowało, że nagranie przestało działać [dopisek: potem okazało się, że aplikacja po prostu przestała działać, a po paru próbach zawiesiła telefon całkowicie - filtr górnoprzepustowy na 10 kHz nie powoduje błędów, działa wykrycie]

Ale dla mnie było to już wystarczające, bo skoro wiem jak piszczy, to mogę napisać program, który te piski rozpozna. Algorytm, który wydawał się pasujący to filtr Goertzela, numerycznie efektywny dla wykrywania obecności określonej częstotliwości w sygnale.

private static double GoertzelFilter(float[] samples, double freq, int start, int end) { double sPrev = 0.0; double sPrev2 = 0.0; int j; double normalizedfreq = freq / SIGNAL_SAMPLE_RATE; double coeff = 2 * Math.Cos(2 * Math.PI * normalizedfreq); for (j = start; j < end; j++) { double s = samples[j] + coeff * sPrev - sPrev2; sPrev2 = sPrev; sPrev = s; } double power = sPrev2 * sPrev2 + sPrev * sPrev - coeff * sPrev * sPrev2; return power; }

Prosty przykład + świetna biblioteka NAudio do robienia wszystkiego z dźwiękiem dla C# zaowocowały prostą aplikacją, najpierw analizującą sygnał zapisany w pliku WAV, a potem "na bieżąco" wykrywającą obecność częstotliwości 15595 Hz.

I już witaliśmy się z gąską, ale trzeba to jeszcze zaprząc do aplikacji dla Windows Phone, a najlepiej dla Windows 10. Taką aplikację popełniłem, ale wymaga jeszcze pewnego dopasowania dla lepszego wykrywania tonów, a obsługa aplikacji UWP w NAudio sprawia jeszcze trochę problemów (lepiej jest dla WinRT) - przede wszystkim wersja dla UWP jest "do samodzielnego skompilowania", jeszcze nie dostępna oficjalnie.

A samo urządzonko? Rozkłada się na dwa kawałki, z których jeden może służyć jako "nóżka" do telefonu, zasilane jest jedną malutką baterią. Kosztowało mnie około 10 zł i trochę zabawy, a planowałem kupić zasadniczo zdalny wyzwalacz na Bluetooth. Zaślepiony ceną jednak kupiłem coś takiego...

Pomyślałem więc, że wykorzystam to w pewnym innym projekcie, tworząc wirtualne urządzenie wejściowe i oprogramuję sobie te piski. W moim laptopie jednak nagranie pisku z urządzonka wywołało inny efekt w Audacity:

Okazuje się, że laptop wyposażony jest w filtr dolnoprzepustowy, który wycina wysokie częstotliwości. I w tym momencie napis na opakowaniu gadżetu o niekompatybilności z pewnymi odmianami Sony Xperia jest jasny - one również wyposażone są w taki filtr. 

sprzęt programowanie

Komentarze

0 nowych
mmm777   4 #1 29.02.2016 22:16

Ładne, przyjemna lektura.
Nawisem mówiąc przycisk do migawki BT zaczął działać w WP10. (Trochę koślawie, bo wyświetla suwak głośności, ale...)

KyRol   17 #2 29.02.2016 23:03

Mnie to głęboko zastanawia co ludzi trzyma jeszcze przy windach, mając jakikolwiek pomysł na uruchomienie czegokolwiek trzeba pisać od zera biblioteki i sterowniki, nawet do byle pierwszego-lepszego wyświetlacza. Jakoś w świecie GNU/Linuksa czy tym bardziej Androida takich rozterek nie ma, znaczna część kodu dawno temu gdzieś leżakuje na jakimś githubie. Pozostaje zebrać pomysły, opracować koncepcję - i bam - gotowe.

W windzie jest tak, że co chwilę jakiś menadżer wpada co rusz na genialne pomysły i kończy się to przeważnie tak, że po roku albo dwóch developer musi pisać wszystko od nowa. A bo to zmienił się format aplikacji, a bo przebudowano sklep, a teraz ambitnych menadżerów dopadła schizofrenia o nazwie onecore.

Autor edytował komentarz.
Jusko   12 #3 29.02.2016 23:27

Ciekawy wpis, muszę przyznać :-)

@KyRol #2: Tak ogólnie - to trzyma oprogramowanie. GNU/Linux to świetny system, ale żadne czary nie zmienią tego, że to Winda ma najbogatszą bazę softu. Oczywiście do tego wielkiego worka softu, wrzucam też gry.

mktos   9 #4 01.03.2016 00:13

@mmm777: Zależy jaki - jak są takie Android+iOS dwa w jednym to wyświetla suwak głośności, jak jest tylko Android to działa bez tego (bo symuluje klawisz Enter w Androidzie, a klawisz Vol+ w iOS) :-)

@KyRol: Mnie tam osobiście przy Windows Phone trzyma fakt, że mi się bardzo źle korzysta z Androida ;-)

Nie wiem czy trzeba pisać od zera, przenośność kodu pomiędzy UWP i WinRT jest bardzo duża - z Silverlightem gorzej, ale też nie jest tak źle jak myślałem, że będzie.

KyRol   17 #5 01.03.2016 00:16

@Jusko: Ta, na komórce?! Przecież mój komentarz był w kontekście innych architektur niż x86. I tak, rozumiem to, że niektórzy zjedli zęby w si szarpach i dot netach tylko to nie tłumaczy co rocznego budowania koła do wozu od nowa...

Jusko   12 #6 01.03.2016 00:26

@KyRol #5: Zatem przepraszam - odniosłem się w nieprawidłowym kontekście.

KyRol   17 #7 01.03.2016 00:51

@mktos: No teraz spójrz na user agent w moich komentarzach. Dzisiaj kupując urządzenie z Androidem wcale z niego nie musimy korzystać, przykładem na to jestem ja, przykładem jest mój Nexus 5 czy inne, liczne chińskie tygrysy, które do takiego celu można zaadaptować. Przenośność przenośnością, a jakoś nikt nie para się kompleksowymi projektami. Dlaczego? Bo wszystko i tak trzeba pisać od zera. Prosty przykład na Raspberry Pi Linuksowi makerzy mają i czym się pochwalić i z czym pokazać, a w mobilnych windach pisze się sterowniki do tak podstawowych modułów jak wyświetlacze. No i do tego jeszcze są ograniczenia.

mktos   9 #8 01.03.2016 10:00

@KyRol: O Windows 10 IoT (bo o nim mowa w kontekście wyświetlaczy?) nie wypowiem się, bo nie miałem żadnej styczności. Jakoś akurat ten projekt w jego obecnej formie niekoniecznie do mnie przemawia.

Choć sam sens przenośności kodu (i umiejętności) pomiędzy aplikacjami na desktop, tablet, telefon i embedded bardzo sobie chwalę, z doświadczenia na innej platformie.

golem14   4 #9 01.03.2016 18:01

Tak mi się skojarzyło z zestawami "Mały Elektronik", tam też można było zmontować coś co wydaje piski... Biorąc jednak pod uwagę włożony trud w zbadanie tego ustrojstwa i zasady działania, możesz się teraz pokusić o zaprogramowanie wyzwalania dowolnej aplikacji dowolnym zdarzeniem, np. kamerki dźwiękiem otwieranych drzwi :-D

tylko_prawda   10 #10 02.03.2016 16:46

WTF? Zdalne selfie?
A ten Windows z filmu coś mi przypomina mojego Cinnamona.

Autor edytował komentarz.
  #11 06.03.2016 23:29

Windows Phone? WTF? Przecież na to nawet splunąć nie warto, nie nadaje się do niczego.