# Public API Reference

#### CrystalLipSyncController API

**Namespace:** `CrystalLipSync`

**Properties**

| Property           | Type          | Description                                                                        |
| ------------------ | ------------- | ---------------------------------------------------------------------------------- |
| `Mood`             | `LipSyncMood` | Get/set the current emotional mood.                                                |
| `VisemeWeights`    | `float[]`     | Current smoothed viseme weights (length 15). Read-only array, updated every frame. |
| `DominantViseme`   | `int`         | Index of the viseme with the highest weight.                                       |
| `CurrentVolume`    | `float`       | Current RMS volume level of the analyzed audio.                                    |
| `SpectralCentroid` | `float`       | Spectral centroid of the current frame in Hz.                                      |
| `HighFreqRatio`    | `float`       | Ratio of high-to-total frequency energy (0...1).                                   |
| `BandEnergies`     | `float[]`     | Normalized energy per frequency band (6 bands).                                    |
| `IsActive`         | `bool`        | Whether the AudioSource is assigned and playing.                                   |

**Events**

| Event                    | Signature         | Description                                         |
| ------------------------ | ----------------- | --------------------------------------------------- |
| `OnVisemeWeightsUpdated` | `Action<float[]>` | Fired every frame after viseme weights are updated. |

**Methods**

```csharp
// Get or set the AudioSource at runtime
AudioSource GetAudioSource();
void SetAudioSource(AudioSource source);

// Assign or clear a profile at runtime
void SetProfile(CrystalLipSyncProfile newProfile);

// Set the mood at runtime
void SetMood(LipSyncMood newMood);

// Reinitialize the analyzer with a new FFT size
void ReinitializeAnalyzer(FFTSizeOption newFftSize);
```

#### CrystalLipSyncBlendshapeTarget API

**Namespace:** `CrystalLipSync`

**Properties**

| Property          | Type   | Description                                             |
| ----------------- | ------ | ------------------------------------------------------- |
| `UseMoodMappings` | `bool` | Whether mood-specific mappings are enabled (read-only). |

**Methods**

```csharp
// Set the controller reference at runtime
void SetController(CrystalLipSyncController ctrl);

// Set the global weight multiplier (0...200)
void SetGlobalWeight(float weight);

// Enable or disable mood-specific mappings
void SetUseMoodMappings(bool enabled);

// Set a mapping for a specific viseme and mood
void SetMapping(LipSyncMood moodType, VisemeType viseme, int blendshapeIndex, float weight = 100f);

// Set a mapping for the Neutral mood (shorthand)
void SetMapping(VisemeType viseme, int blendshapeIndex, float weight = 100f);

// Get the mapping array for a specific mood
VisemeBlendshapeMapping[] GetMappingsForMood(LipSyncMood moodType);
```

#### CrystalEyeBlink API

**Namespace:** `CrystalLipSync`

**Properties**

| Property          | Type                  | Description                                   |
| ----------------- | --------------------- | --------------------------------------------- |
| `TargetMesh`      | `SkinnedMeshRenderer` | Get/set the blendshape mesh.                  |
| `BlinkLeftIndex`  | `int`                 | Get/set the left eye blink blendshape index.  |
| `BlinkRightIndex` | `int`                 | Get/set the right eye blink blendshape index. |
| `BlinkBothIndex`  | `int`                 | Get/set the combined blink blendshape index.  |

**Methods**

```csharp
// Force a blink from script
void TriggerBlink(bool triggerDoubleBlink = false);

// Re-run auto-detection (clears current mappings first)
void Redetect();

// Run auto-detection on a specific root GameObject
void AutoDetectBlendshapes(GameObject root);
```

#### CrystalTextLipSync API

**Namespace:** `CrystalLipSync`

**Properties**

| Property    | Type   | Description                                          |
| ----------- | ------ | ---------------------------------------------------- |
| `IsPlaying` | `bool` | Whether a text viseme sequence is currently playing. |

**Methods**

```csharp
// Begin lip-syncing to a text string.
// charsPerSecond: match your typewriter speed (default: 10)
// speed: playback speed multiplier (default: 1)
void PlayText(string text, float charsPerSecond = 10f, float speed = 1f);

// Stop the current text lip sync. Mouth smoothly returns to rest.
void Stop();

// Set the blendshape target at runtime
void SetTarget(CrystalLipSyncBlendshapeTarget target);

// Set the controller at runtime
void SetController(CrystalLipSyncController controller);
```

**Example**

```csharp
var textSync = character.GetComponent<CrystalTextLipSync>();

// Sync to dialogue text at typewriter speed
textSync.PlayText("Welcome to our village, traveler.", charsPerSecond: 12f);

// Stop when dialogue is dismissed
textSync.Stop();
```

#### CrystalMicrophoneLipSync API

**Namespace:** `CrystalLipSync`

**Properties**

| Property      | Type     | Description                                             |
| ------------- | -------- | ------------------------------------------------------- |
| `IsCapturing` | `bool`   | Whether the microphone is currently capturing.          |
| `DeviceName`  | `string` | Name of the microphone device in use (empty = default). |

**Events**

| Event              | Signature | Description                           |
| ------------------ | --------- | ------------------------------------- |
| `OnCaptureStarted` | `Action`  | Fired when microphone capture begins. |
| `OnCaptureStopped` | `Action`  | Fired when microphone capture ends.   |

**Methods**

```csharp
// Start capturing from the configured microphone device.
void StartCapture();

// Start capturing from a specific device (empty/null = default).
void StartCapture(string deviceName);

// Stop capturing and restore the AudioSource to its previous state.
void StopCapture();

// Set the controller at runtime. Must call StopCapture() first if active.
void SetController(CrystalLipSyncController ctrl);

// Set the microphone device name. Must call StopCapture() first if active.
void SetDevice(string deviceName);

// Toggle whether the AudioSource is muted during capture.
void SetMutePlayback(bool mute);

// Get all available microphone device names.
static string[] GetAvailableDevices();
```

**Example**

```csharp
var micSync = character.GetComponent<CrystalMicrophoneLipSync>();

// Start with default mic
micSync.StartCapture();

// Or specify a device
string[] devices = CrystalMicrophoneLipSync.GetAvailableDevices();
if (devices.Length > 0)
    micSync.StartCapture(devices[0]);

// Stop when done
micSync.StopCapture();
```

#### CrystalTextToViseme API

**Namespace:** `CrystalLipSync`\
**Class:** `static CrystalTextToViseme`

```csharp
// Convert text to a list of timed viseme entries.
// Rich-text tags are stripped automatically.
// When matchTypewriterDuration is true (default), the total sequence
// duration is normalized to match textLength / charsPerSecond, ensuring
// the mouth animation ends exactly when the typewriter finishes.
static List<VisemeEntry> Generate(string text, float charsPerSecond = 10f,
    bool matchTypewriterDuration = true);

// Get total duration of a viseme sequence in seconds.
static float GetTotalDuration(List<VisemeEntry> entries);
```

**Duration normalization:** By default, `Generate()` scales all entry durations so the total matches the typewriter reveal time. Without this, consonants (0.6x weight) and silences (0.4x weight) would cause the sequence to finish earlier than the text. The relative rhythm between vowels, consonants, and pauses is preserved.

**`VisemeEntry` struct:**

| Field      | Type         | Description                  |
| ---------- | ------------ | ---------------------------- |
| `viseme`   | `VisemeType` | The viseme to display.       |
| `duration` | `float`      | Seconds to hold this viseme. |

**Character mapping highlights:**

* Digraphs: `th` → TH, `sh`/`ch` → CH, `ng` → NN, `ph` → FF, `ee` → I, `oo` → U, `ou` → U, `ai`/`ay` → E, `aw` → O
* Vowels: `a` → AA, `e` → E, `i` → I, `o` → O, `u` → U
* Consonants: `p`/`b`/`m` → PP, `f`/`v` → FF, `d`/`t` → DD, `k`/`g`/`c`/`q` → KK, `s`/`z` → SS, `n` → NN, `r` → RR, `j` → CH, `w` → U, `y` → I
* Spaces/punctuation → SIL (merged when consecutive)

#### CrystalLipSyncAutoMapper API

**Namespace:** `CrystalLipSync`\
**Class:** `static CrystalLipSyncAutoMapper`

```csharp
// Auto-map blendshapes to visemes. Returns int[15] where each value
// is a blendshape index (-1 = unmapped).
static int[] AutoMap(SkinnedMeshRenderer smr);

// Score a mesh for viseme suitability. Higher = more viseme-like.
static int ScoreMesh(SkinnedMeshRenderer smr);

// Find the best SkinnedMeshRenderer in a hierarchy for visemes.
// Returns null if none found.
static SkinnedMeshRenderer FindBestVisemeMesh(GameObject root);
```
