Forum: Projekte & Code Spielzeugformantvocoder (Sprachsynthese)


von Christian B. (casandro)


Angehängte Dateien:

Lesenswert?

OK, eines vorweg. Der Code ist in Pascal. Ganz einfach deswegen, da das 
nicht nur meine Lieblingsprogrammiersprache ist, sondern auch noch 
leicht von jedem verstanden werden kann. Mir geht es hier nicht darum, 
einen perfekten Code abzuliefern, sondern darum, einfach mal zu zeigen, 
wie einfach das geht.

Das Programm macht einen einfachen Formant-Vocoder. Ein Vocoder 
simuliert den Stimmtrakt. Im Prinzip ist das eine Anregung welche aus 
einem Dirakpuls und Rauschen besteht (Verhältnis einstellbar) und diesen 
dann durch 2 Filter schickt welche eine Frequenzerhöhung bei einer 
bestimmten Frequenz (Formant) machen. 2 Formanten reichen für 
verständliche Sprache bereits aus.

Die Filter sind parallelgeschaltet und sind rekursive Filter 2. Ordnung. 
Vor rekursiven Filtern haben manche Leute Angst, wenn man die redoch in 
vernünftigen Rahmen betreibt sind die stabil.

Filterstruktur:

x---->+->------->y
      |\    |
      | \   T
      |  \b1|
       \    |
        \   T
         \b2|

Also grob gesagt kommt das Signal bei x rein, und dazu wird dann das 
einfach verzögerte, mit b1 multiplizierte Ausgangssignal addiert, sowie 
das zweifach verzögerte, mit b2 multiplizierte Ausgangssignal addiert.

Vereinfach gesagt bestimmt b2 die Güte des Filters und b1 die Frequenz.

Stabil ist der Filter in einem Dreieck mit der Spitze b1=0 und b2=1 
sowie der Basis b2=-1 und -2<=b1<=2.

Die Eingabe des Programmes ist
Dauer Grundfreq Stimmh. Rauschh.Formant1 Formant2
Beispiel:
1       100     1       0       1000    1400
1       100     1       0       500     2300
1       100     1       0       320     3200
1       100     1       0       500     1000
1       100     1       0       320     800
1       100     1       0       700     1800
1       100     1       0       500     1500
1       100     1       0       320     1650
1       100     0       1       3000    3500
1       100     0       1       2000    2500

Das sind mehrere Laute, jeweils eine Sekunde lang. Es beginnt mit A E I 
O U, Ä Ö Ü und dann kommen 2 experimentelle Frikale.

Die Ausgabe ist:
Zeit/s seit Dateianfang, Leerzeichen, Abtastwert
Das Programm sox kann dieses Format direkt als "dat" verarbeiten.

Wenn man mal genau nachsieht, in welchen Wertebereichen die einzelnen 
Variablen sind, und man die Cosinusse durch Tabellen ersetzt kann man 
das bestimmt auch mit Festkommaartithmetrik machen und somit problemlos 
auf einem AVR laufen lassen.

von Christian B. (casandro)


Angehängte Dateien:

Lesenswert?

Daisy Daisy give me your answer to....

Der Beginn des berühmten Liedes welches man hier
http://chaosradio.ccc.de/ctv037.html
in ganzer Länge hören kann.

von Micha (Gast)


Lesenswert?

Hallo Christian!

Ich finde Deine Postings sehr interessant und überlege, sie auf einem 
AVR zu konvertieren. Allerdings woher bekommt man die Parameter für 
Phoneme? Selber ausprobieren? (Ich habe noch nicht wirklich selber 
gesucht :-)

Gruß, Michael

von Christian B. (casandro)


Lesenswert?

Micha wrote:
> Hallo Christian!
>
> Ich finde Deine Postings sehr interessant und überlege, sie auf einem
> AVR zu konvertieren.

Danke

> Allerdings woher bekommt man die Parameter für
> Phoneme? Selber ausprobieren? (Ich habe noch nicht wirklich selber
> gesucht :-)

In dem Fall des Musikstücks habe ich die einfach vom Spektrogramm 
abgelesen. Ansonsten ist die Wikipedia dein Freund. Zumindest bei 
Vokalen.
http://de.wikipedia.org/wiki/Formant

> Gruß, Michael

von Christian B. (casandro)


Lesenswert?

Ohh eins hab ich noch vergessen. Vielleicht ist es sinnvoll das ganze in 
eine ISR zu stecken. dann kann man die Parameter leichter ändern.

von Mario (Gast)


Lesenswert?

Christian,

interessante sache, hatte mich noch nie damit beschäftigt! Ich hab mir 
mal den Code angesehen, da ist mir aufgefallen, das der implementierte 
Filter nicht zur textuellen Beschreibung passt:
Im code steht:
filter1_d1:=y1;

lt. Beschreibung würde ich hier ein:
filter1_d1:=x;

erwarten. Selbiges für den 2ten filter. Die Abbildung des Filters hilft 
mir da auch nicht weiter ...

Gruß
Mario

von Christian B. (casandro)


Lesenswert?

Mario wrote:
> Christian,
>
> interessante sache, hatte mich noch nie damit beschäftigt! Ich hab mir
> mal den Code angesehen, da ist mir aufgefallen, das der implementierte
> Filter nicht zur textuellen Beschreibung passt:
> Im code steht:
> filter1_d1:=y1;
>
> lt. Beschreibung würde ich hier ein:
> filter1_d1:=x;
>
> erwarten. Selbiges für den 2ten filter. Die Abbildung des Filters hilft
> mir da auch nicht weiter ...

Ahh, das ist ein Implementationsdetail. Würde ich den Wert von X nehmen, 
so müsste ich X verändern und beide Filter würden zusammenfallen.


Ich glaub so kann man das besser darstellen:


X--->Y1------>
    |
| |   V
|f1<-d1
|     |
|     V
f2<--d2


Die Summationsstelle ist somit Y1. Das macht den Code einfacher und ich 
brauche weniger Variablen.

> Gruß
> Mario

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.