first commit
This commit is contained in:
107
examples/example_babble.c
Normal file
107
examples/example_babble.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* EXAMPLE: Pure Random Motor Babbling
|
||||
*
|
||||
* This example bypasses all linguistic rules, phoneme definitions, and attractor states.
|
||||
* It sends completely random vectors to the articulatory physics engine.
|
||||
*
|
||||
* That is the sound of raw, uncoordinated motor commands! Without a 'brain'
|
||||
* (linguistic rules) to smooth things out and coordinate the glottis with the tongue,
|
||||
* you essentially get the acoustic equivalent of a seizure or extreme distress.
|
||||
*
|
||||
* It proves that human speech is less about having a mouth and more about the
|
||||
* incredibly precise, learned choreography of closing it.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "articulator.h"
|
||||
#include "transcriber.h"
|
||||
|
||||
extern char RAW_OUTPUT_BUFFER[];
|
||||
extern const ortho_rule_t ORTHO_IPA[];
|
||||
extern const ortho_rule_t ORTHO_POLISH[];
|
||||
extern const ortho_rule_t ORTHO_HUNGARIAN[];
|
||||
extern const ortho_rule_t ORTHO_GERMAN[];
|
||||
extern const ortho_rule_t ORTHO_CYRILLIC[];
|
||||
extern const ortho_rule_t ORTHO_ORCISH[];
|
||||
|
||||
float randf(float min, float max) { return min + ((float)rand() / (float)RAND_MAX) * (max - min); }
|
||||
|
||||
// PURE RANDOM GENERATOR
|
||||
// No concept of vowels, consonants, or linguistic structure.
|
||||
// Just random points in the 6-dimensional muscle space.
|
||||
f6_t generate_random_target(void) {
|
||||
f6_t t;
|
||||
|
||||
// 1. Randomize Articulators (0.0 - 1.0)
|
||||
t.tx = randf(0.0, 1.0); // Tongue Place (Front <-> Back)
|
||||
t.ty = randf(0.0, 1.0); // Tongue Height (Roof <-> Open)
|
||||
t.la = randf(0.0, 1.0); // Lips (Closed <-> Wide)
|
||||
t.lr = randf(0.0, 1.0); // Rounding (Spread <-> Round)
|
||||
|
||||
// Velum (Oral vs Nasal)
|
||||
// We use discrete values (0.0 or 1.0) because continuous random values (e.g. 0.5)
|
||||
// create physically ambiguous targets that result in constant air leakage.
|
||||
t.nz = (rand() % 5 == 0) ? 1.0f : 0.0f; // 20% chance of nasal
|
||||
|
||||
// 2. Randomize Glottis (Voicing)
|
||||
// We bias slightly towards voicing (0.5-1.0) to ensure audible output.
|
||||
// Using pure 0.0-1.0 would result in ~40% silent breathing.
|
||||
if (rand() % 10 < 2) {
|
||||
t.gt = randf(0.0, 0.4); // Breath/Silence
|
||||
} else {
|
||||
t.gt = randf(0.5, 0.9); // Voicing/Creak
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void motor_babble(int count) {
|
||||
printf("\n=== Random Motor Babble (%d gestures) ===\n", count);
|
||||
|
||||
// Allocate memory for the stream (1 chunk per gesture)
|
||||
f6_t* stream = malloc(sizeof(f6_t) * count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
stream[i] = generate_random_target();
|
||||
}
|
||||
|
||||
// Run the physics simulation
|
||||
simulate_motor_stream(stream, count);
|
||||
|
||||
char word[256];
|
||||
|
||||
printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER);
|
||||
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA);
|
||||
printf("IPA: \"%s\"\n", word);
|
||||
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH);
|
||||
printf(" PL: \"%s\"\n", word);
|
||||
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN);
|
||||
printf(" HU: \"%s\"\n", word);
|
||||
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN);
|
||||
printf(" DE: \"%s\"\n", word);
|
||||
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC);
|
||||
printf(" RU: \"%s\"\n", word);
|
||||
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH);
|
||||
printf("ORC: \"%s\"\n", word);
|
||||
|
||||
free(stream);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
srand(time(NULL));
|
||||
|
||||
// Generate 5 random sequences of varying length
|
||||
for (int i = 0; i < 5; i++) {
|
||||
motor_babble(8 + rand() % 8);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
178
examples/example_names.c
Normal file
178
examples/example_names.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* EXAMPLE: Structured Name Generation (The "Brain")
|
||||
*
|
||||
* Unlike the random motor babbler, this program applies high-level linguistic
|
||||
* constraints to the articulatory physics engine. It defines specific phoneme
|
||||
* subsets (Languages) and grammar rules (Syllable Structure) to guide the mouth.
|
||||
*
|
||||
* It demonstrates that by constraining the chaos of the physics engine with
|
||||
* simple rules (Attractor States), we can generate distinct, recognizable
|
||||
* "accents" or "languages".
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "articulator.h"
|
||||
#include "transcriber.h"
|
||||
|
||||
extern char RAW_OUTPUT_BUFFER[];
|
||||
extern const phoneme_t PHONEME_DB[];
|
||||
extern const ortho_rule_t ORTHO_IPA[];
|
||||
extern const ortho_rule_t ORTHO_POLISH[];
|
||||
extern const ortho_rule_t ORTHO_HUNGARIAN[];
|
||||
extern const ortho_rule_t ORTHO_GERMAN[];
|
||||
extern const ortho_rule_t ORTHO_CYRILLIC[];
|
||||
extern const ortho_rule_t ORTHO_ORCISH[];
|
||||
|
||||
/* --- LANGUAGE DEFINITIONS --- */
|
||||
|
||||
/* Standard Fantasy/English-ish */
|
||||
const char* LANG_COMMON[] = {"p", "b", "t", "d", "k", "g", "m", "n", "f", "v", "s", "z", "ʃ", "h", "r",
|
||||
"l", "w", "j", "i", "u", "e", "o", "a", "ə", "ɪ", "ɛ", "æ", "ɔ", NULL};
|
||||
const char* LANG_SLAVIC[] = {
|
||||
// Vowels (Simple 6 system)
|
||||
"i", "u", "e", "o", "a", "ɨ", // ɨ is Polish 'y'
|
||||
|
||||
// Consonants
|
||||
"p", "b", "t", "d", "k", "g", "m", "n", "ɲ", // n, ń
|
||||
"f", "v", "s", "z", "x", // f, w, s, z, ch
|
||||
"ts", "dz", // c, dz
|
||||
"ʃ", "ʒ", "tʃ", "dʒ", // sz, ż, cz, dż
|
||||
"ɕ", "ʑ", "tɕ", "dʑ", // ś, ź, ć, dź
|
||||
"l", "r", "j", "w", // l, r, j, ł
|
||||
NULL};
|
||||
/* Harsh/Orcish (Back of throat, Guttural) */
|
||||
const char* LANG_ORCISH[] = {"k", "g", "q", "ɢ", "ʔ", "x", "χ", "ʁ", "h", "p", "b", "t", "d", "u", "o", "ɑ", "ɔ", NULL};
|
||||
|
||||
/* Soft/Elvish (Liquids, Fricatives, Front Vowels) */
|
||||
const char* LANG_ELVISH[] = {"p", "b", "t", "d", "m", "n", "f", "v", "s", "z", "ʃ", "ʒ", "θ", "ð",
|
||||
"l", "ʎ", "r", "w", "j", "i", "y", "e", "ø", "a", "ɛ", "œ", NULL};
|
||||
|
||||
/* --- FILTER HELPER --- */
|
||||
|
||||
/* Check if an IPA symbol exists in the allowed list */
|
||||
int is_allowed(const char* ipa, const char** allowed_list) {
|
||||
for (int i = 0; allowed_list[i] != NULL; i++) {
|
||||
if (strcmp(ipa, allowed_list[i]) == 0) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- UPDATED GENERATOR --- */
|
||||
|
||||
void generate_name(const char* race_name, const char** allowed_sounds, int syllables) {
|
||||
printf("\n=== Generating %s Name (%d syl) ===\n", race_name, syllables);
|
||||
|
||||
// 1. Build Index Cache for this Language
|
||||
int v_indices[100], v_count = 0;
|
||||
int c_indices[100], c_count = 0;
|
||||
|
||||
for (int i = 0; PHONEME_DB[i].ipa != NULL; i++) {
|
||||
// Only add if it's in the allowed list
|
||||
if (is_allowed(PHONEME_DB[i].ipa, allowed_sounds)) {
|
||||
if (is_vowel_index(i)) {
|
||||
if (v_count < 100) v_indices[v_count++] = i;
|
||||
} else {
|
||||
if (c_count < 100) c_indices[c_count++] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v_count == 0 || c_count == 0) {
|
||||
printf("Error: No sounds found for %s\n", race_name);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Build Sequence (C-V-C pattern)
|
||||
int len = 0;
|
||||
int seq[100];
|
||||
|
||||
for (int s = 0; s < syllables; s++) {
|
||||
// Onset
|
||||
if (rand() % 10 < 7) seq[len++] = c_indices[rand() % c_count];
|
||||
// Nucleus
|
||||
seq[len++] = v_indices[rand() % v_count];
|
||||
// Coda
|
||||
if (rand() % 10 < 4) seq[len++] = c_indices[rand() % c_count];
|
||||
}
|
||||
|
||||
// 3. Simulate & Transcribe
|
||||
simulate_sequence(seq, len);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
srand(time(NULL));
|
||||
char word[256];
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
generate_name("Human", LANG_COMMON, 2 + i);
|
||||
printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA);
|
||||
printf("IPA: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH);
|
||||
printf(" PL: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN);
|
||||
printf(" HU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN);
|
||||
printf(" DE: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC);
|
||||
printf(" RU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH);
|
||||
printf("ORC: \"%s\"\n", word);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
generate_name("Slavic", LANG_SLAVIC, 2 + i);
|
||||
printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA);
|
||||
printf("IPA: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH);
|
||||
printf(" PL: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN);
|
||||
printf(" HU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN);
|
||||
printf(" DE: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC);
|
||||
printf(" RU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH);
|
||||
printf("ORC: \"%s\"\n", word);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
generate_name("Orcish", LANG_ORCISH, 2 + i);
|
||||
printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA);
|
||||
printf("IPA: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH);
|
||||
printf(" PL: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN);
|
||||
printf(" HU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN);
|
||||
printf(" DE: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC);
|
||||
printf(" RU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH);
|
||||
printf("ORC: \"%s\"\n", word);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
generate_name("Elvish", LANG_ELVISH, 2 + i);
|
||||
printf("RAW: \"%s\"\n", RAW_OUTPUT_BUFFER);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_IPA);
|
||||
printf("IPA: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_POLISH);
|
||||
printf(" PL: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_HUNGARIAN);
|
||||
printf(" HU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_GERMAN);
|
||||
printf(" DE: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_CYRILLIC);
|
||||
printf(" RU: \"%s\"\n", word);
|
||||
transcribe(RAW_OUTPUT_BUFFER, word, ORTHO_ORCISH);
|
||||
printf("ORC: \"%s\"\n", word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user