( asch | 2019. 09. 27., p – 22:49 )

Én mostanában írtam ilyen programot. A problémára vannak libek, amik megoldják ezt: újramintavétlezik a hangot úgy, hogy folyamatosan állítgathatod a mintavétel sebességarányát. Van belőle olyan is, ami a hangmagasságot nem módosítja. Ilyet úgy lehet csinálni, hogy frekvenciatartományban végzed a hosszabbítást (egyszerűen szólva FFT oda, lassítás és FFT vissza, de pontosan nem tudom hogyan működik).

Én a speex libre építve csináltam meg ezt a funkciót.

Szabályzóból nagyon egyszerűt csináltam: beállítottam egy ideális pufferméretet, ami annál kisebb, azt lassítja, ami nagyobb azt gyorsítja progresszíven.

Ezzel a setuppal teljesen használható volt a végeredmény még úgyis, hogy TCP-n átkergettem SSH-n keresztül a VPS szerveremen oda vissza. A két végpont pedig az otthoni hálózatomon Wifin ment.

Itt írtam blogbejegyzést a programról, bár ilyen részletekbe asszem nem merültem bele ott:

https://hup.hu/node/151733

Ez a programrész csinálja az újramintavételezést: stdio-n kapja a bemeneti hangblokkot és a ki/bemeneti frekvenciát minden periódusban. A speexet állítgatja és meghívj az újramintavételezést és köpi ki a kimenetet. Plusz kiadja, hogy hány bájtot használt fel a bemenetből, és hány hasznos van a kimeneten. Ha ez eltér a blokkmérettől, akkor a hívó oldalnak újra be kell adni a feldolgozatlan mintákat, illetve a hiányos kimeneti blokkot csak a következő körben tudja kiegészíteni. A drivernek ugye mindig tele blokkokat kell adni, és olyat is kapunk tőle:

https://github.com/rizsi/rcom/blob/master/speexcmd/cmd-speexdsp.c#L123

Az egyszerűség kedvéért külön programok összjátékával megy: a hangot a Java veszi a beépített Java audió libbel. ffmpeg veszi a képet külön streambe. És ezeket a streameket fogja össze a Java egyetlen TCP streambe és küldi egy szerveren át a másik olalra. Az ott demultiplexeli, és az ellenoldani ffmpeg-be csatornázza be a képet. A hangot a puffer méregetésével szabályzott speex lassító/gyorsítóba, végül pedig Java Audio kimenetre.

(A képet viszont szabályzatlanul amint jönnek a kockák kiteszem: így is élvezhető, csak olyan kodeket kellett az ffmpeg-ből választani - vagy beparaméterezni, ami nem pufferel)

Virtualizált Windowson valamiért akadozott az egész, mintha nem lenne tickless az ütemezés. Ehhez a működéshez ugye az kell, hogy minden azonnal ütemezve legyen, amikor lehet: a Linux jól megoldja és tök szépen működik. Pedig nem volt túlterhelve a processzor, mégsem ment simán a folyamat.

Echo canceller: ebből a Pulseaudio beépítettje egészen jó, azt csak be kell kapcsolni parancssori paraméterből, és megy is.

Az echo cancellereket legjobb HW közelben megoldani, mivel ekkor biztosan lehet tudni, hogy a kimenet és a bemenet ugyanarról az órajelről működik. Ha ez nem teljesül (pl külön USB-s mikrofon van egy másik hangkártyáról ketyegő hangszóróval), akkor sokkal bonyolultabb jól megcsinálni. Gyanúm, hogy a Skype sikere mögött az is áll, hogy erre a nehéz feladatra jó megoldást adtak, és így gagyi vagy gagyin beállított vasakon is élvezhető.

Plusz problémája az echo cancellernek, hogy ha más program is hangot ad ki, az is beleszól. Ezért is jó ha a PulseAudióra bízzuk: ő már az összes kimeneti stream mixjén tudja futtatni a visszhangelnyomást. Hasonlóan nem hülyül bele a menet közbeni hangerőállításba sem. (Amit lehet tapasztalni, ha virtuális gépben Szkájpolsz, és a host Linuxon állítgatod a hangerőt: meghülyül a visszhangelnyomója.)

Hogy Windows alatt is működjön az RCOM, ezért kísérleteztem "saját" echo cancellel is, de nem lett igazán jó, és natív Windows híján tesztelni sem nagyon tudtam. Virtualizálva a fent említett ütemezési probléma miatt akadozik az egész. Plusz probléma, hogy ehhez az egész audió kezelést át kellett alakítanom: a hangforrások mixelését nem tudtam a driverre bízni, hanem először mixelni kellett és utána belevezetni a visszhangelnyomóba.

Ekkor jöttem rá arra is, hogy a Skype miért csörög minden beszélgetés előtt még akkor is ha előbb rákattint az ellenoldal: azért, mert a csörgéssel tudja inicializálni a visszhangelnyomó alrendszerét. Ugye ez a kimenet és a bement között talál korrelációt, de csak akkor tudja inicializálni magát, ha van kiadott hang.

Emiatt van az is, hogy telefonhívás elején néha visszhangos, de amint bekalibrálta magát az elnyomórendszer, akkor elmúlik ez a zavar.