Ten zeszyt służy jako wstęp do korzystania z biblioteki emuR do analizy korpusów mowy w języku R.

Zaczniemy od załadowania biblioteki emuR:

library(emuR)

Attaching package: ‘emuR’

The following object is masked from ‘package:base’:

    norm

Po ściągnięciu i rozpakowaniu archiwum z tego linku: http://mowa.clarin-pl.eu/korpusy/clarin-small.zip

Zakładając, że jesteśmy w katalogu, gdzie rozpakowano powyższe archiwum, możemy wczytać naszą bazę:

db <- load_emuDB('clarin', verbose = FALSE)

Uwaga: argument verbose jest tu potrzebny tylko do poprawnego wyświetlania w tym zeszycie - normalnie nie jest potrzebny.

W pamięci znalazła się zmienna o nazwie db, ale w tej postaci nie można wiele z niej wyczytać. Biblioteka emuR zawiera specjalne funkcje do wyświetlania zawartości bazy.

Możemy, na przykład, wyświetlić listę sesji:

list_sessions(db)

Albo poszczególnych paczek:

list_bundles(db)

Możemy obejrzeć hierarchię opisującą naszą bazę:

list_levelDefinitions(db)

Możemy też uruchomić specjalny intefejs webowy do przeglądania i edycji całej bazy:

serve(db)
Navigate your browser to the EMU-webApp URL: http://ips-lmu.github.io/EMU-webApp/ (should happen automatically)
Server connection URL: ws://localhost:17890
To stop the server press 'clear' button in the EMU-webApp or close/reload the webApp in your browser.
emuR websocket service established
emuR websocket service closed
[1] FALSE

Ale przede wszystkim możemy wykonywać specjalne kwerendy do wyszukiwania konkrentnych segmentów w bazie.

Poszukajmy wszystkich samogłosek dla mówcy nagranego w sesji SES0100:

segs=query(db,'Phoneme=a|e|i|I|o|u', sessionPattern = "SES0100")

Otrzymujemy listę segmentów, która zawiera mnóstwo ciekawych informacji. Spójrzmy na jej srtukturę:

str(segs)
Classes ‘emuRsegs’, ‘emusegs’ and 'data.frame': 1689 obs. of  16 variables:
 $ labels            : chr  "o" "e" "a" "o" ...
 $ start             : num  4410 4670 4850 5470 5590 ...
 $ end               : num  4490 4790 4990 5550 5720 ...
 $ utts              : chr  "SES0100:rich001" "SES0100:rich001" "SES0100:rich001" "SES0100:rich001" ...
 $ db_uuid           : chr  "604e8448-241d-11e7-9cad-507b9d83c0f9" "604e8448-241d-11e7-9cad-507b9d83c0f9" "604e8448-241d-11e7-9cad-507b9d83c0f9" "604e8448-241d-11e7-9cad-507b9d83c0f9" ...
 $ session           : chr  "SES0100" "SES0100" "SES0100" "SES0100" ...
 $ bundle            : chr  "rich001" "rich001" "rich001" "rich001" ...
 $ start_item_id     : int  753449 753452 753454 753458 753460 753463 753467 753472 753474 753478 ...
 $ end_item_id       : int  753449 753452 753454 753458 753460 753463 753467 753472 753474 753478 ...
 $ level             : chr  "Phoneme" "Phoneme" "Phoneme" "Phoneme" ...
 $ start_item_seq_idx: int  9 12 14 18 20 23 27 32 34 38 ...
 $ end_item_seq_idx  : int  9 12 14 18 20 23 27 32 34 38 ...
 $ type              : chr  "SEGMENT" "SEGMENT" "SEGMENT" "SEGMENT" ...
 $ sample_start      : int  70560 74720 77600 87520 89440 94400 140800 149280 152320 166400 ...
 $ sample_end        : int  71840 76640 79840 88800 91520 97280 142400 151360 156320 170720 ...
 $ sample_rate       : int  16000 16000 16000 16000 16000 16000 16000 16000 16000 16000 ...
 - attr(*, "query")= chr "Phoneme=a|e|i|I|o|u"
 - attr(*, "type")= chr "segment"
 - attr(*, "database")= chr "clarin"

Z powyższej tabelki można wyczytać dużo ciekawych informacji i pisać własne programy, które je przetworzą, ale emuR posiada narzędzia, które nam jeszcze bardziej ułatwią życie.

Czasami baza danych zawiera już przetworzone dane (tak jak w tym przypadku), ale czasami trzeba użyć biblioteki wrassp do przeliczenia informacji z korpusu. W każdym przypadku używamy poniższego polecenia.

Następujące polecenie wylicza (wczytuje z dysku) formanty dla wszystkich segmentów. Argument cut jest kolejnym udogodnieniem, gdyż dla każdego segmentu zwraca tylko jedną wartość, znajdującą się dokładnie pośrodku każdego segmentu. Argument consistentOutputType jest potrzebny do ułatwienia pracy z wynikową tabelką jaką zwraca to polecenie:

td <- get_trackdata(db, seglist = segs, ssffTrackName = 'Formants', cut=0.5,
                    consistentOutputType = FALSE,  verbose = FALSE)
td

Tak jak widać, powyższa tabelka zawiera dokładnie tyle samo elementów co tabelka segmentów. Niestety, informacje o samogłosce i jej formantach są w dwóch różnych tabelkach. Połączymy je zatem w nowej tabelce i nazwiemy bardziej intuicyjnie:

dane <- data.frame(vowel=segs$labels, F1=td$fm1, F2=td$fm2)
dane

Mamy tutaj tylko jeden mały problem. Algorytmy aproksymacji formantów czasami zawodzą, a w takich sytuacjach najczęściej wpisują jakąś przewidywalną wartość - w tym przypadku 0. Część znalezionych formantów ma wartość 0, więc warto je usunąć z naszej listy przed narysowaniem. Użyjemy do tego wygodnej biblioteki dplyr:

library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
dane <- filter(dane,F1>0 & F2>0)

W tej chwili straciliśmy ok. 3% danych, ale mamy pewność, że nie ma w nich “śmieci”.

Teraz można już rysować zawartość stworzonej tabelki używając funkcji plot, ale są sposoby dobre i lepsze. Otóż, ktoś stworzył świetną bibliotekę do wyświetlania fonemów w przestrzeni 2D i warto z niej skorzystać:

library(phonR)

Rysowanie używając tej biblioteki jest trywialne:

plotVowels(dane$F1,dane$F2,dane$vowel)

Ale przy odrobinie czytania dokumentacji i ustawiania argumentów, można uzyskać bardzo ładne rysunki:

plotVowels(dane$F1, dane$F2,
           vowel = dane$vowel, 
           var.col.by = dane$vowel, 
           plot.tokens = TRUE, 
           pch.tokens = dane$vowel,
           plot.means = TRUE, 
           pch.means = dane$vowel,
           cex.tokens = 1.2,
           alpha.tokens = 0.4, 
           cex.means = 4, 
           ellipse.line = TRUE, 
           pretty = TRUE)

LS0tCnRpdGxlOiAiU2Ftb2fFgm9za2kgdyBlbXVSIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUZW4gemVzenl0IHPFgnXFvHkgamFrbyB3c3TEmXAgZG8ga29yenlzdGFuaWEgeiBiaWJsaW90ZWtpICplbXVSKiBkbyBhbmFsaXp5IGtvcnB1c8OzdyBtb3d5IHcgasSZenlrdSBSLgoKWmFjem5pZW15IG9kIHphxYJhZG93YW5pYSBiaWJsaW90ZWtpIGVtdVI6CmBgYHtyfQpsaWJyYXJ5KGVtdVIpCmBgYAoKClBvIMWbY2nEhWduacSZY2l1IGkgcm96cGFrb3dhbml1IGFyY2hpd3VtIHogdGVnbyBsaW5rdToKaHR0cDovL21vd2EuY2xhcmluLXBsLmV1L2tvcnB1c3kvY2xhcmluLXNtYWxsLnppcAoKWmFrxYJhZGFqxIVjLCDFvGUgamVzdGXFm215IHcga2F0YWxvZ3UsIGdkemllIHJvenBha293YW5vIHBvd3nFvHN6ZSBhcmNoaXd1bSwgbW/FvGVteSB3Y3p5dGHEhyBuYXN6xIUgYmF6xJk6CmBgYHtyfQpkYiA8LSBsb2FkX2VtdURCKCdjbGFyaW4nLCB2ZXJib3NlID0gRkFMU0UpCmBgYAoKVXdhZ2E6IGFyZ3VtZW50IGB2ZXJib3NlYCBqZXN0IHR1IHBvdHJ6ZWJueSB0eWxrbyBkbyBwb3ByYXduZWdvIHd5xZt3aWV0bGFuaWEgdyB0eW0gemVzenljaWUgLSBub3JtYWxuaWUgbmllIGplc3QgcG90cnplYm55LgoKVyBwYW1pxJljaSB6bmFsYXrFgmEgc2nEmSB6bWllbm5hIG8gbmF6d2llIGBkYmAsIGFsZSB3IHRlaiBwb3N0YWNpIG5pZSBtb8W8bmEgd2llbGUgeiBuaWVqIHd5Y3p5dGHEhy4gQmlibGlvdGVrYSBlbXVSIHphd2llcmEgc3BlY2phbG5lIGZ1bmtjamUgZG8gd3nFm3dpZXRsYW5pYSB6YXdhcnRvxZtjaSBiYXp5LgoKTW/FvGVteSwgbmEgcHJ6eWvFgmFkLCB3ecWbd2lldGxpxIcgbGlzdMSZIHNlc2ppOgpgYGB7cn0KbGlzdF9zZXNzaW9ucyhkYikKYGBgCgoKQWxibyBwb3N6Y3plZ8OzbG55Y2ggcGFjemVrOgpgYGB7cn0KbGlzdF9idW5kbGVzKGRiKQpgYGAKCk1vxbxlbXkgb2JlanJ6ZcSHIGhpZXJhcmNoacSZIG9waXN1asSFY8SFIG5hc3rEhSBiYXrEmToKYGBge3J9Cmxpc3RfbGV2ZWxEZWZpbml0aW9ucyhkYikKYGBgCgpNb8W8ZW15IHRlxbwgdXJ1Y2hvbWnEhyBzcGVjamFsbnkgaW50ZWZlanMgd2Vib3d5IGRvIHByemVnbMSFZGFuaWEgaSBlZHljamkgY2HFgmVqIGJhenk6CmBgYHtyfQpzZXJ2ZShkYikKYGBgCgoKQWxlIHByemVkZSB3c3p5c3RraW0gbW/FvGVteSB3eWtvbnl3YcSHIHNwZWNqYWxuZSBrd2VyZW5keSBkbyB3eXN6dWtpd2FuaWEga29ua3JlbnRueWNoIHNlZ21lbnTDs3cgdyBiYXppZS4KClBvc3p1a2FqbXkgd3N6eXN0a2ljaCBzYW1vZ8WCb3NlayBkbGEgbcOzd2N5IG5hZ3JhbmVnbyB3IHNlc2ppIFNFUzAxMDA6CmBgYHtyfQpzZWdzPXF1ZXJ5KGRiLCdQaG9uZW1lPWF8ZXxpfEl8b3x1Jywgc2Vzc2lvblBhdHRlcm4gPSAiU0VTMDEwMCIpCmBgYAoKCk90cnp5bXVqZW15IGxpc3TEmSBzZWdtZW50w7N3LCBrdMOzcmEgemF3aWVyYSBtbsOzc3R3byBjaWVrYXd5Y2ggaW5mb3JtYWNqaS4gU3DDs2pyem15IG5hIGplaiBzcnR1a3R1csSZOgpgYGB7cn0Kc3RyKHNlZ3MpCmBgYAoKClogcG93ecW8c3plaiB0YWJlbGtpIG1vxbxuYSB3eWN6eXRhxIcgZHXFvG8gY2lla2F3eWNoIGluZm9ybWFjamkgaSBwaXNhxIcgd8WCYXNuZSBwcm9ncmFteSwga3TDs3JlIGplIHByemV0d29yesSFLCBhbGUgKmVtdVIqIHBvc2lhZGEgbmFyesSZZHppYSwga3TDs3JlIG5hbSBqZXN6Y3plIGJhcmR6aWVqIHXFgmF0d2nEhSDFvHljaWUuCgpDemFzYW1pIGJhemEgZGFueWNoIHphd2llcmEganXFvCBwcnpldHdvcnpvbmUgZGFuZSAodGFrIGphayB3IHR5bSBwcnp5cGFka3UpLCBhbGUgY3phc2FtaSB0cnplYmEgdcW8ecSHIGJpYmxpb3Rla2kgKndyYXNzcCogZG8gcHJ6ZWxpY3plbmlhIGluZm9ybWFjamkgeiBrb3JwdXN1LiBXIGthxbxkeW0gcHJ6eXBhZGt1IHXFvHl3YW15IHBvbmnFvHN6ZWdvIHBvbGVjZW5pYS4KCk5hc3TEmXB1asSFY2UgcG9sZWNlbmllIHd5bGljemEgKHdjenl0dWplIHogZHlza3UpIGZvcm1hbnR5IGRsYSB3c3p5c3RraWNoIHNlZ21lbnTDs3cuIEFyZ3VtZW50IGBjdXRgIGplc3Qga29sZWpueW0gdWRvZ29kbmllbmllbSwgZ2R5xbwgZGxhIGthxbxkZWdvIHNlZ21lbnR1IHp3cmFjYSB0eWxrbyBqZWRuxIUgd2FydG/Fm8SHLCB6bmFqZHVqxIVjxIUgc2nEmSBkb2vFgmFkbmllIHBvxZtyb2RrdSBrYcW8ZGVnbyBzZWdtZW50dS4gQXJndW1lbnQgYGNvbnNpc3RlbnRPdXRwdXRUeXBlYCBqZXN0IHBvdHJ6ZWJueSBkbyB1xYJhdHdpZW5pYSBwcmFjeSB6IHd5bmlrb3fEhSB0YWJlbGvEhSBqYWvEhSB6d3JhY2EgdG8gcG9sZWNlbmllOgpgYGB7cn0KdGQgPC0gZ2V0X3RyYWNrZGF0YShkYiwgc2VnbGlzdCA9IHNlZ3MsIHNzZmZUcmFja05hbWUgPSAnRm9ybWFudHMnLCBjdXQ9MC41LAogICAgICAgICAgICAgICAgICAgIGNvbnNpc3RlbnRPdXRwdXRUeXBlID0gRkFMU0UsICB2ZXJib3NlID0gRkFMU0UpCnRkCmBgYAoKClRhayBqYWsgd2lkYcSHLCBwb3d5xbxzemEgdGFiZWxrYSB6YXdpZXJhIGRva8WCYWRuaWUgdHlsZSBzYW1vIGVsZW1lbnTDs3cgY28gdGFiZWxrYSBzZWdtZW50w7N3LiBOaWVzdGV0eSwgaW5mb3JtYWNqZSBvIHNhbW9nxYJvc2NlIGkgamVqIGZvcm1hbnRhY2ggc8SFIHcgZHfDs2NoIHLDs8W8bnljaCB0YWJlbGthY2guIFBvxYLEhWN6eW15IGplIHphdGVtIHcgbm93ZWogdGFiZWxjZSBpIG5hendpZW15IGJhcmR6aWVqIGludHVpY3lqbmllOgpgYGB7cn0KZGFuZSA8LSBkYXRhLmZyYW1lKHZvd2VsPXNlZ3MkbGFiZWxzLCBGMT10ZCRmbTEsIEYyPXRkJGZtMikKZGFuZQpgYGAKCgpNYW15IHR1dGFqIHR5bGtvIGplZGVuIG1hxYJ5IHByb2JsZW0uIEFsZ29yeXRteSBhcHJva3N5bWFjamkgZm9ybWFudMOzdyBjemFzYW1pIHphd29kesSFLCBhIHcgdGFraWNoIHN5dHVhY2phY2ggbmFqY3rEmcWbY2llaiB3cGlzdWrEhSBqYWvEhcWbIHByemV3aWR5d2FsbsSFIHdhcnRvxZvEhyAtIHcgdHltIHByenlwYWRrdSAwLiBDesSZxZvEhyB6bmFsZXppb255Y2ggZm9ybWFudMOzdyBtYSB3YXJ0b8WbxIcgMCwgd2nEmWMgd2FydG8gamUgdXN1bsSFxIcgeiBuYXN6ZWogbGlzdHkgcHJ6ZWQgbmFyeXNvd2FuaWVtLiBVxbx5amVteSBkbyB0ZWdvIHd5Z29kbmVqIGJpYmxpb3Rla2kgKmRwbHlyKjoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmRhbmUgPC0gZmlsdGVyKGRhbmUsRjE+MCAmIEYyPjApCmBgYAoKClcgdGVqIGNod2lsaSBzdHJhY2lsacWbbXkgb2suIDMlIGRhbnljaCwgYWxlIG1hbXkgcGV3bm/Fm8SHLCDFvGUgbmllIG1hIHcgbmljaCAixZttaWVjaSIuCgpUZXJheiBtb8W8bmEganXFvCByeXNvd2HEhyB6YXdhcnRvxZvEhyBzdHdvcnpvbmVqIHRhYmVsa2kgdcW8eXdhasSFYyBmdW5rY2ppIGBwbG90YCwgYWxlIHPEhSBzcG9zb2J5IGRvYnJlIGkgbGVwc3plLiBPdMOzxbwsIGt0b8WbIHN0d29yennFgiDFm3dpZXRuxIUgYmlibGlvdGVrxJkgZG8gd3nFm3dpZXRsYW5pYSBmb25lbcOzdyB3IHByemVzdHJ6ZW5pIDJEIGkgd2FydG8geiBuaWVqIHNrb3J6eXN0YcSHOgpgYGB7cn0KbGlicmFyeShwaG9uUikKYGBgCgoKUnlzb3dhbmllIHXFvHl3YWrEhWMgdGVqIGJpYmxpb3Rla2kgamVzdCB0cnl3aWFsbmU6CmBgYHtyLGZpZy53aWR0aD0xMH0KcGxvdFZvd2VscyhkYW5lJEYxLGRhbmUkRjIsZGFuZSR2b3dlbCkKYGBgCgpBbGUgcHJ6eSBvZHJvYmluaWUgY3p5dGFuaWEgZG9rdW1lbnRhY2ppIGkgdXN0YXdpYW5pYSBhcmd1bWVudMOzdywgbW/FvG5hIHV6eXNrYcSHIGJhcmR6byDFgmFkbmUgcnlzdW5raToKYGBge3IsZmlnLndpZHRoPTEwfQpwbG90Vm93ZWxzKGRhbmUkRjEsIGRhbmUkRjIsCiAgICAgICAgICAgdm93ZWwgPSBkYW5lJHZvd2VsLCAKICAgICAgICAgICB2YXIuY29sLmJ5ID0gZGFuZSR2b3dlbCwgCiAgICAgICAgICAgcGxvdC50b2tlbnMgPSBUUlVFLCAKICAgICAgICAgICBwY2gudG9rZW5zID0gZGFuZSR2b3dlbCwKICAgICAgICAgICBwbG90Lm1lYW5zID0gVFJVRSwgCiAgICAgICAgICAgcGNoLm1lYW5zID0gZGFuZSR2b3dlbCwKICAgICAgICAgICBjZXgudG9rZW5zID0gMS4yLAogICAgICAgICAgIGFscGhhLnRva2VucyA9IDAuNCwgCiAgICAgICAgICAgY2V4Lm1lYW5zID0gNCwgCiAgICAgICAgICAgZWxsaXBzZS5saW5lID0gVFJVRSwgCiAgICAgICAgICAgcHJldHR5ID0gVFJVRSkKYGBgCgoKCgoKCgoKCgoKCgo=