107 lines
3.2 KiB
C
107 lines
3.2 KiB
C
/*
|
|
* 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;
|
|
} |