Skocz do zawartości

Pomocna odpowiedź

No to teraz kolej na zabawę z syntezą.

Jak wspomniałem, nie chcę tu używać pełnego syntezatora, a po prostu nagrać pojedyncza komunikaty lub ich fragmenty. Robiłem to już kiedyś, ale tamta aplikacja nie mogła być publikowana z przyczyn licencyjnych - licencja Ivony do prywatnego użytku nie pozwalała na publikację wygenerowanych przez nią komunikatów.

Na szczęście dzisiaj sytuacja jest inna: RHVoice nie ma takich obostrzeń i mogłem go użyć do nagrań.

Teoretycznie sprawa jest prosta: nagrywamy komunikaty pozwalające złożyć z nich odczyt np. liczby, i odtwarzam we właściwej kolejności. Tyle, że to nie zawsze wystarczy.

Jako użytkownik "firmowych" gadających urządzeń mogę powiedzieć co mnie denerwuje. Np. mówiąca waga łazienkowa - mało, że strasznie ślamazarzy, to jeszcze wymawia poszczególne wyrazy bez najmniejszej próby jakiejkolwiek intonacji, robiąc przy tym potężne pauzy między wyrazami.

Postanowiłem więc zrobić coś lepiej.

Po pierwsze, potrzebna jest kontrola prędkości odtwarzania dźwięku. Bo przecież komuś może odpowiadać piękny głos lektora odczytującego powoli wynik pomiaru, ktoś inny będzie preferować dwukrotnie przyspieszony odczyt bo chce jak najszybciej poznać wynik.

Tu akurat skorzystałem z gotowego rozwiązania: Sonic, a konkretniej wersji sonic_lite. Niestety - nie wiem czemu funkcja sonicFlushStream kończy się sygnałem jedenastym na pececie lub restartem ESP32, postanowiłem nie wnikać w szczegóły i zamiast tego wrzucić do strumienia wejściowego fragment ciszy. Oczywiście bez flush Sonic utnie jakiś ostatni fragment, ale w tej sytuacji po prostu utnie ciszę (co będzie w praktyce niezauważalne).

Po drugie - intonacja. Teoretycznie da się stworzyć pełną melodię zdania, ale wymagałoby to nagrania każdego słowa w kilku różnych wersjach. Oczywiście to mało realne - przede wszystkim zabrakłoby pamięci, poza tym nie uśmiecha mi się ręczna obróbka kilkuset plików dźwiękowych. Na szczęście kiedyś ćwiczyłem to właśnie na Ivonie, i zastosowałem tu uproszczony sposób.

Słowa zapisuję w dwóch wersjach: z melodią opadającą i wznoszącą. Melodię wznoszącą uzyskuję poprzez dodanie pytajnika - nie jest to super doskonały sposób, ale na potrzeby odczytywania wyników pomiarów wystarczający. Teraz wystarczy tak skonstruować frazę, aby kończyła się wyrazem z melodią opadającą, a poprzedzające wyrazy miały na przemian melodię wznoszącą i opadającą. Efekt w załączniku - ciekawe, kto uzna to za lepszy sposób generowania zdania. W załączniku dwa konkretne przykłady: demovoice.zip

Oczywiście nie każdy musi to lubić - w gotowym urządzeniu będzie możliwość wyboru czy chcemy stosować skorygowaną melodię, czy nie.

Dla chętnych kod w Pythonie użyty przeze mnie do tworzenia plików dźwiękowych. Działa na Linuksie, wymaga:

  • zainstalowanego RHVoice z polskimi głosami (z githuba)
  • modułu rhvoice_wrapper (przez pip)
  • programu sox (z dystrybucji, może być konieczne dodanie formatów z libsox)
#!/usr/bin/env python3

import sys, struct, subprocess,os
args=sys.argv[1:]
dtrim = True
arg=args.pop(0)

if arg == '-n':
    arg=args.pop(0)
    dtrim=False
if arg not in ['natan','alicja','magda']:
    raise Exception("Zły głos %s" % arg)
voice = arg
fname=os.path.join(voice,args.pop(0))
if not os.path.exists(voice):
    os.mkdir(voice)
txt=args[0]
from rhvoice_wrapper import TTS
tts=TTS(threads=1,quiet=True)
tts.set_params(relative_rate=1.3)
vox=[]
vox=tts.get(text=txt,voice=voice,format_='pcm')
tts.join()
le=int(len(vox) / 2)
vox=struct.unpack('%dh' % le, vox)
    
if dtrim:
    for i in range(2,le):
        if abs(vox[i]) > 128:
            break
    beg=max(i-200,2)
#    print(beg,i)
    for i in range(le-10,beg,-1):
        if abs(vox[i]) > 128:
            break
    fin = min(i+200,le-10)
    print(fin,i,le)
else:
    beg=100
    fin=len(vox) - 100
vox=vox[beg:fin]
le=len(vox)
vox=struct.pack('%dh' % le, *vox)
p=subprocess.Popen(['sox','-t','raw','-e','signed-integer','-r','24000','-b','16',
    '-','-t','raw','-e','u-law','-r','16000',fname,'norm'],stdin=subprocess.PIPE)
p.communicate(vox)

Oczywiście to taka wstępna wersja programu, ale może komuś się przydać. Sposób wywołania:

python3.py [-n] głos nazwa 'komunikat'

Podanie parametru -n spowoduje, że nie będzie ucinana cisza przed i po komunikacie.

Jak widać, zrezygnowałem z głosu Cezary. Mówi bardzo ładnie, ale na koniec mówienia wydziela z siebie jakieś głębokie westchnienie i absolutnie nie miałem zamiaru bawić się w jego ucinanie, szczególnie że męski głos Natan jest dużo wyraźniejszy, szczególnie przy przyspieszeniu,.

I jeszcze jedno - już nie związane z syntezą.

Suwmiarka Vorel (do której jest przeznaczona przystawka) ma automatyczny wyłącznik. Program wykrywa że suwmiarka się wyłączyła, i co jakiś czas informuje 'brak sygnału'.

Ponieważ nie chcę tu wprowadzać żadnej dodatkowej automatyki typu usypianie (musiałbym dodać odcinanie napięcia od suwmiarki i wzmacniacza, bo nawet w trybie wyłączenia prąd jest za duży jak na urządzenie bateryjne). Zamiast tego jeśli suwmiarka nie jest używana, program prosi o wyłączenie urządzenia.

I tu pojawia się problem: po podłączeniu USB (do naładowania akumulatora) suwmiarka darłaby się informując o braku sygnału prosząc o wyłączenie...

Postanowiłem obejść to w najprostszy możliwy sposób: podłączyć pin 5V przez dzielnik do któregoś pinu (najbardziej by pasował GPIO4) i na num pojawiłoby się napięcie, zostałoby wyłączone anonsowanie braku sygnału i prośby o wyłączenie.

Ciekawe, co o tym sądzicie?

Tyle na dziś.

 

  • Lubię! 1
  • 2 tygodnie później...

Prace idą do przodu.

Wczoraj udało mi się zmieścić to w obudowie razem z oryginalną anteną. Głośniczek 24x15x4 mm działa nadspodziewanie dobrze, głos jest nadspodziewanie wyraźny, musiałem dodać regulację głośności bo na pełnej strasznie się darł 🙂

Urządzenie jest na razie przypięte recepturką do suwmiarki - paski samoprzylepne są jednorazowe, a przewiduję jeszcze kilka razy dobrać się do wnętrza obudowy.

Nie podłączałem na razie zasilania samej suwmiarki - przy testach jest wygodniejsze zasilanie z wbudowanej baterii, poza tym muszę opracować coś co nie pozwoli na włożenie baterii do suwmiarki (może się to dla niej smutno skończyć).

Przy okazji powstaje wersja z językiem angielskim (dwa głosy, męski i żeński). Wersja polskojęzyczna operuje trzema możliwymi głosami (magda, michal, natan). Przy okazji: @romanro, Twoja Magda świetnie się sprawdza w takim zastosowaniu! Zrobiliście kawał dobrej roboty!

Ponieważ urządzenie pobiera zaledwie 36 mA jeśli nie gada i nie ma włączonego BLE - muszę kupić mniejszy akumulator (w tej chwili mam 450  mAh wyjęty z poprzedniej wersji, myślę że jakiś 250 - 300 mAh powinien wystarczyć).

Zastanawiam się jeszcze nad możliwością zablokowania BLE. Nie każdy tego potrzebuje, szczególnie że w ostatnich wersjach Androida nie da się ustawić takiego głosu jak chcę. Bez BLE konstrukcja się upraszcza bo nie trzeba kombinować z anteną...

Niestety nie mogłem dopaść elementów aby zrobić porządną płytkę. O ile regulator napięcia dla suwmiarki mogę zrobić na tranzystorze (akurat mam potrzebne w wersji SMD) - nie mam diod Schottky potrzebnych do zasilenia wzmacniacza. Szkoda - ale w wolnej chwili postaram się zrobić przynajmniej projekt, a sprawdzenie i wykonanie pozostawię chętnym 🙂

 No nic, trzeba skończyć program, opublikować gotowy projekt i myśleć nad ulepszeniami 🙂

 

 

  • Lubię! 1

Ale się ładnie nabrałem!

Zrobiłem piękny końcowy projekt obudowy, wydrukowałem, wsadziłem elektronikę, zamknąłem, przykleiłem, i...

...i okazało się, że po podłączeniu kabla USB nie mam praktycznie dostępu do wyłącznika. Znaczy się... dostęp niby jest, ale mniej więcej taki jak w XIAO S3 do przycisków r/b. Czyli tak jakby zgodnie z zastosowaną płytką 🙂

miarka_o.thumb.jpg.42fb8f9c3625a9bbcfe68e73a07b939e.jpg

Na szczęście gdzieś na dnie szuflady został jeszcze jeden pasek samoprzylepny - po przeniesieniu wyłącznika na drugą stronę obudowy zrobiło się jakoś wygodniej 🙂

miarka_n.thumb.jpg.bb407091b0793d543022a1508aa4ac64.jpg

Może podesłać pomysł kolesiom z Seeeeeeeedstudio? 🙂

No cóż - tu już w elektronice grzebać nie będę, trzeba lecieć dalej z programem. Ciekawostka: RHVoice z głosem kilkanaście MB brzmi jakieś dziesięć razy naturalniej i czytelniej niż piper-tts z prawie 200 MB. Zdaje się że ta fascynacja AI zaczyna wychodzić bokiem...

  • Lubię! 2

No cóż - trzeba zacząć się chwalić czymś gotowym.

Postanowiłem nie czekać aż dopieszczę program: nie wiem kiedy skończę, ale dziś mogę pokazać coś działającego.

Przypominam: przystawka pasuje do suwmiarki Vorel oraz do tejże firmy miernika głębokości bieżnika.

Ale przede wszystkim kod: demosuw.zip

Kod zawiera dwie wersje językowe, wybierane w pliku i18n.h poprzez zakomentowanie linii:

#define VOICE_IS_PL

Zakomentowanie tej linii spowoduje skompilowanie angielskiej wersji.

Obie wersje zawierają po dwa głosy (męski i żeński).

Czujnik ładowania jest wyłączony, jeśli ktoś koniecznie chce może w pliku common.h zakomentować/odkomentować linie:

// wyłącznie czujnika ładowania
#define DISABLE_CHARGER

// wyłączenie bluetooth
#define DISABLE_BLE

Potrzebna jest jedynie biblioteka ESP8266Audio (najlepiej w najnowszej wersji). Program został skompilowany z wersją board 3.2.0, ale powinien działać z dowolną wersją 3.x (powinien... nie znaczy że będzie). Ustawienia powinny być następujące:

demosub_params.thumb.png.a8b3257049b0400ba57e4c411e2bed88.png

Układ został uproszczony do celów demonstracyjnych. Zamieszczam zarówno schemat, jak i słitaśną focię sztucznym sposobem Frtzlingiem uczynioną 🙂 Układ pinów został tak dobrany, aby można było w prosty sposób zmieścić układ na najmniejszej płytce stykowej 170 otworów.

simple.thumb.png.43ec26b641c2b8320c84678128a4536c.pngminiboard_bb.thumb.png.cd5a93e60c8072d10b9126ced54366b7.png

Kondensatory C1 i C2 mogą mieć od 10 do 100 nF, w moim urządzeniu zastosowałem 8.2 nF (bo takie miałem w szufladzie) i nie zauważyłem błędów odczytu.

W załączniku znajduje się plik STL wtyczki - powinna być wydrukowana z TPU, najlepiej z warstwą mniejszą niż 0.2mm. Osadzenie końcówek przewodów we wtyczce pokazują zdjęcia (przepraszam za jakość, ale nie mam czym zrobić lepiej). Ja po prostu odizolowałem dłuższe końce taśmy AWG28, pocynowałem, włożyłem w otwory i po podgięciu odciąłem zbędne fragmenty. Wtyczka działa bez problemu od dłuższego czasu.

conn_bottom.thumb.jpg.15f9504e91253044e8d12c5f12dd0927.jpgconn_top.thumb.jpg.bbba6a781f86c3d77baca7a6c23973de.jpg

I jeszcze o przycisku.

Układ reaguje na pojedyncze kliknięcie, przytrzymanie, podwójne kliknięcie oraz kliknięcie z przytrzymaniem. W przypadku przytrzymania reakcja następuje po przekroczeniu czasu a nie dopiero po puszczeniu klawisza, co w przypadku pojedynczego przycisku jest wygodniejsze (nie trzeba się zastanawiać czy wystarczająco długo trzymamy klawisz). W normalnym trybie:

  • kliknięcie - wyzwolenie odczytania w trybie odczytu zmian i odczytu na żądanie;
  • przytrzymanie - zmiana trybu: czytanie ciągłe, czytanie zmian, czytanie na żądanie, tryb ładowania (cichy)
  • podwójne kliknięcie - odczyt stanu akumulatora
  • kliknięcie z przytrzymaniem - wejście w tryb ustawień.

W trybie ustawień:

  • kliknięcie - zmiana wartości
  • podwójne kliknięcie - zmiana ustawienia
  • przytrzymanie - zapis wybranych ustawień

Jeśli po 10 sekundach od ostatniego wciśnięcia przycisku nie nastąpi polecenie zapisania, zostaną przywrócone poprzednie wartości.

To chyba tyle z najważniejszych informacji...

Obudowa następnym razem!

 

No cóż - suwmiareczka jest skończona, teraz trzeba tylko jakiś ładny opis zrobić i wrzucić na githuba. Pewnie do końca tygodnia sobie z tym poradzę.

Oczywiście temat gadających urządzeń jest cały czas aktualny, równocześnie z dokumentacją suwmiarki powstaje projekt metrówki z poziomicą, a jeśli mi starczy cierpliwości to jeszcze wagi 🙂

 

  • Lubię! 1
  • 2 tygodnie później...

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...