> ## Documentation Index
> Fetch the complete documentation index at: https://typecast.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# C/C++

The official C/C++ library for the [Typecast API](https://typecast.ai). Convert text to lifelike speech using AI-powered voices.

Compatible with C11 and later versions. Works with CMake, manual compilation, and supports cross-platform development including Windows, Linux, macOS, and embedded systems.

<CardGroup cols={2}>
<Card title="Source Code" icon="github" href="https://github.com/neosapience/typecast-sdk/tree/main/typecast-c">
Typecast C SDK Source Code
</Card>

<Card title="API Documentation" icon="book" href="https://typecast.ai/docs">
Typecast API Documentation
</Card>
</CardGroup>

## Requirements

- CMake 3.14+
- libcurl (with SSL support)
- C11 compatible compiler

<Tabs>
  <Tab title="Linux (Ubuntu/Debian)">
    ```bash
    sudo apt-get install build-essential cmake libcurl4-openssl-dev
    ```
  </Tab>
  
  <Tab title="macOS">
    ```bash
    # libcurl is included with Xcode
    xcode-select --install
    brew install cmake
    ```
  </Tab>
  
  <Tab title="Windows (MSVC)">
    ```powershell
    vcpkg install curl:x64-windows
    ```
  </Tab>
</Tabs>

## Installation

<Tabs>
  <Tab title="CMake (Recommended)">
    Clone the repository and build with CMake:

    ```bash
    git clone https://github.com/neosapience/typecast-sdk.git
    cd typecast-sdk/typecast-c
    mkdir build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=Release
    cmake --build .
    ```
  </Tab>
  
  <Tab title="Manual">
    Compile directly with GCC or Clang:

    ```bash
    git clone https://github.com/neosapience/typecast-sdk.git
    cd typecast-sdk/typecast-c

    # Compile source files
    gcc -c src/typecast.c src/cJSON.c -I include -I src -O2
    
    # Create static library
    ar rcs libtypecast.a typecast.o cJSON.o
    
    # Or compile your application directly
    gcc -o myapp myapp.c src/typecast.c src/cJSON.c \
        -I include -I src -lcurl -O2
    ```
  </Tab>

  <Tab title="FetchContent (CMake)">
    Add to your `CMakeLists.txt`:

    ```cmake
    include(FetchContent)
    FetchContent_Declare(
        typecast
        GIT_REPOSITORY https://github.com/neosapience/typecast-sdk.git
        SOURCE_SUBDIR typecast-c
        GIT_TAG v1.2.13
    )
    FetchContent_MakeAvailable(typecast)

    target_link_libraries(your_target PRIVATE typecast)
    ```
  </Tab>
</Tabs>

<Note>Latest registered version: **v1.2.13** in the SDK Git tags.</Note>

### Build Options

| Option | Default | Description |
|--------|---------|-------------|
| `TYPECAST_BUILD_SHARED` | ON | Build shared library (.dll/.so/.dylib) |
| `TYPECAST_BUILD_STATIC` | OFF | Build static library |
| `TYPECAST_BUILD_EXAMPLES` | ON | Build example programs |
| `TYPECAST_BUILD_TESTS` | ON | Build test programs |

## Quick Start

```c
#include "typecast.h"
#include <stdio.h>

int main() {
    // Initialize client
    TypecastClient* client = typecast_client_create("YOUR_API_KEY");
    if (!client) return 1;

    // Convert text to speech
    TypecastTTSRequest request = {0};
    request.text = "Hello there! I'm your friendly text-to-speech agent.";
    request.voice_id = "tc_672c5f5ce59fac2a48faeaee"; /* Find voice IDs at https://studio.typecast.ai/developers/api/voices */
    request.model = TYPECAST_MODEL_SSFM_V30;
    request.language = "eng";

    TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
    if (response) {
        // Save audio file
        FILE* fp = fopen("output.wav", "wb");
        fwrite(response->audio_data, 1, response->audio_size, fp);
        fclose(fp);

        printf("Audio saved! Duration: %.2fs, Size: %zu bytes\n", 
               response->duration, response->audio_size);

        typecast_tts_response_free(response);
    }

    // Clean up
    typecast_client_destroy(client);
    return 0;
}
```

## Features

The Typecast C/C++ SDK provides powerful features for text-to-speech conversion:

- **C and C++ Support**: Pure C API with optional C++ wrapper for convenience
- **Multiple Voice Models**: Support for `ssfm-v30` (latest) and `ssfm-v21` AI voice models
- **Multi-language Support**: 35+ languages including English, Korean, Spanish, Japanese, Chinese, and more
- **Emotion Control**: Preset emotions (normal, happy, sad, angry, whisper, toneup, tonedown) or smart context-aware inference
- **Audio Customization**: Control loudness (LUFS -70 to 0), pitch (-12 to +12 semitones), tempo (0.5x to 2.0x), and format (WAV/MP3)
- **Voice Discovery**: V2 Voices API with filtering by model, gender, age, and use cases
- **Instant Voice Cloning**: Upload a WAV/MP3 sample and create a custom voice ID
- **Cross-Platform**: Windows, Linux, macOS, ARM (32/64-bit) support
- **Embedded Ready**: Optimized for minimal footprint, cross-compilation support
- **Timestamp TTS**: Word- and character-level alignment data for subtitles, karaoke, and lip-sync
- **Unreal Engine Ready**: Designed for easy integration with game engines
- **Streaming**: Real-time chunked audio delivery for low-latency playback

## Voice Recommendations

Use `typecast_recommend_voices` when you know the desired style but not the exact `voice_id`.

```c
TypecastRecommendedVoicesResponse* voices = typecast_recommend_voices(
    client,
    "warm female voice for a product tutorial",
    3
);

if (voices) {
    for (int i = 0; i < voices->count; i++) {
        printf("%s %s %.3f\n",
            voices->voices[i].voice_id,
            voices->voices[i].voice_name,
            voices->voices[i].score);
    }
    typecast_recommended_voices_response_free(voices);
}
```

Recommendation results contain only `voice_id`, `voice_name`, and `score`. Use `typecast_get_voice` or `typecast_get_voices` when you need detailed metadata such as supported models, emotions, gender, age, or use cases.

## Configuration

Set your API key via environment variable or constructor:

```c
#include <stdlib.h>

// Using environment variable
// export TYPECAST_API_KEY="your-api-key-here"
const char* api_key = getenv("TYPECAST_API_KEY");
TypecastClient* client = typecast_client_create(api_key);

// Or pass directly
TypecastClient* client = typecast_client_create("your-api-key-here");

// Or with custom base URL
TypecastClient* client = typecast_client_create_with_host(
    "your-api-key-here", 
    "https://custom-api.example.com"
);
```

<Info>
When requests go through your own proxy, pass the proxy host and omit the API key by passing `NULL` or an empty string. The SDK will not send the `X-API-KEY` header for empty or missing keys. Requests to the default Typecast host still require an API key.
</Info>

```c Proxy without API key
TypecastClient* client = typecast_client_create_with_host(
    NULL,
    "https://your-proxy.example.com"
);
```

## Advanced Usage

### Emotion Control (ssfm-v30)

ssfm-v30 offers two emotion control modes: **Preset** and **Smart**.

<Tabs>
  <Tab title="Smart Mode">
    Let the AI infer emotion from context:

    ```c
    TypecastTTSRequest request = {0};
    request.text = "Everything is going to be okay.";
    request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
    request.model = TYPECAST_MODEL_SSFM_V30;
    request.language = "eng";

    // Smart emotion with context
    TypecastPrompt prompt = {0};
    prompt.emotion_type = TYPECAST_EMOTION_TYPE_SMART;
    prompt.previous_text = "I just got the best news!";   // Optional context
    prompt.next_text = "I can't wait to celebrate!";      // Optional context
    request.prompt = &prompt;

    TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
    ```
  </Tab>

  <Tab title="Preset Mode">
    Explicitly set emotion with preset values:

    ```c
    TypecastTTSRequest request = {0};
    request.text = "I am so excited to show you these features!";
    request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
    request.model = TYPECAST_MODEL_SSFM_V30;
    request.language = "eng";

    // Preset emotion
    TypecastPrompt prompt = TYPECAST_PROMPT_DEFAULT();
    prompt.emotion_type = TYPECAST_EMOTION_TYPE_PRESET;
    prompt.emotion_preset = TYPECAST_EMOTION_HAPPY;  // normal, happy, sad, angry, whisper, toneup, tonedown
    prompt.emotion_intensity = 1.5f;                 // Range: 0.0 to 2.0
    request.prompt = &prompt;

    TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
    ```
  </Tab>
</Tabs>

### Audio Customization

Control loudness, pitch, tempo, and output format:

```c
TypecastTTSRequest request = {0};
request.text = "Customized audio output!";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
request.model = TYPECAST_MODEL_SSFM_V30;
request.language = "eng";

// Configure output settings
TypecastOutput output = TYPECAST_OUTPUT_DEFAULT();
output.use_target_lufs = 1;
output.target_lufs = -14.0f;                    // Range: -70 to 0 (LUFS)
output.audio_pitch = 2;                        // Range: -12 to +12 semitones
output.audio_tempo = 1.2f;                     // Range: 0.5x to 2.0x
output.audio_format = TYPECAST_AUDIO_FORMAT_MP3;  // Options: WAV, MP3
request.output = &output;


TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
if (response) {
    const char* ext = (response->format == TYPECAST_AUDIO_FORMAT_MP3) ? "mp3" : "wav";
    char filename[64];
    snprintf(filename, sizeof(filename), "output.%s", ext);
    
    FILE* fp = fopen(filename, "wb");
    fwrite(response->audio_data, 1, response->audio_size, fp);
    fclose(fp);
    
    printf("Duration: %.2fs, Format: %s\n", response->duration, ext);
    typecast_tts_response_free(response);
}
```

### Control silence duration

Requires **1.2.13 or later**.

`remove_silence_ms` specifies the **silence duration to retain**, not the amount to remove. Use an integer from `0` to `1000` ms. `0` removes detected silence; omission or `null` disables duration-based silence removal.

Standard, streaming, and timestamp TTS use `output.remove_silence_ms`; Compose uses `segments[].output.remove_silence_ms` on each `tts` segment. Returned timestamps align with the processed audio, and explicit `pause` segments are preserved.

Streaming's default leading-silence trimming is separate. Small values such as `0` can leave gaps between playable chunks; allow sufficient playback buffering and test with your content.

C preserves the existing public-struct ABI. With `client` and a `TypecastTTSRequest request` prepared, use the extension function; do not add a field to an existing struct. `NULL` disables processing; an integer pointer preserves explicit values including `0`.

```c
int remaining_silence_ms = 300;
TypecastTTSResponse* audio = typecast_text_to_speech_with_silence(
    client, &request, &remaining_silence_ms
);
if (audio != NULL) typecast_tts_response_free(audio);
```

| Use | Function |
| --- | --- |
| Standard TTS | `typecast_text_to_speech_with_silence` |
| Streaming | `typecast_text_to_speech_stream_with_silence` |
| Timestamps | `typecast_text_to_speech_with_timestamps_and_silence` |
| Save to file | `typecast_generate_to_file_with_silence` |
| Composer defaults | `typecast_speech_composer_defaults_with_silence` |
| Composer segment | `typecast_speech_composer_say_with_silence` |

### Generate audio to a file

Use `typecast_generate_to_file` when you want the SDK to synthesize speech and write the audio bytes directly to a local file. The model defaults to `ssfm-v30`, and `.mp3` / `.wav` extensions infer the output format when no output format is set. Browse available voice IDs on the [Voices](https://studio.typecast.ai/developers/api/voices) page.

```c
TypecastGenerateToFileRequest request = {0};
request.text = "Hello from Typecast.";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee"; /* Find voice IDs at https://studio.typecast.ai/developers/api/voices */

TypecastErrorCode code = typecast_generate_to_file(client, "output.mp3", &request);
if (code != TYPECAST_SUCCESS) {
    fprintf(stderr, "Failed to generate audio: %s\n", typecast_error_string(code));
}
```

For C++ wrapper users:

```cpp
typecast::GenerateToFileRequest request;
request.text = "Hello from Typecast.";
request.voiceId = "tc_672c5f5ce59fac2a48faeaee"; // Find voice IDs at https://studio.typecast.ai/developers/api/voices

auto response = client.generateToFile("output.mp3", request);
```

### Text pauses

Use text pause markup when you only need silent gaps inside one composed text segment. Put `<|5s|>`, `<|1s|>`, `<|0.3s|>`, or `<|0.34413s|>` directly in the text. The value is interpreted as seconds and must end with `s`. This keeps the pause expression visible in plain text without adding separate pause calls.

```c
TypecastSpeechComposer* composer = typecast_speech_composer_create(client);
TypecastComposerSettings defaults = {0};
defaults.voice_id = "tc_672c5f5ce59fac2a48faeaee";
defaults.model = TYPECAST_MODEL_SSFM_V30;
typecast_speech_composer_defaults(composer, &defaults);

typecast_speech_composer_say(
    composer,
    "Hello<|5s|>Nice to meet you<|1s|>Today<|2s|>how does the weather feel?",
    NULL
);

TypecastTTSResponse* audio = typecast_speech_composer_generate(composer, TYPECAST_AUDIO_FORMAT_WAV);
typecast_tts_response_free(audio);
typecast_speech_composer_destroy(composer);
```

### Multi-speaker composition

Use the composer chaining API when one output file needs different voices or per-segment options such as pitch, tempo, or prompt. The composer sends segments to `POST /v1/text-to-speech/compose`, which returns WAV or MP3 directly. Set silence removal explicitly on TTS segments; explicit pauses are preserved.

```c
TypecastSpeechComposer* composer = typecast_speech_composer_create(client);
TypecastComposerSettings defaults = {0};
defaults.voice_id = "tc_672c5f5ce59fac2a48faeaee";
defaults.model = TYPECAST_MODEL_SSFM_V30;
typecast_speech_composer_defaults(composer, &defaults);

typecast_speech_composer_say(composer, "Hello there", NULL);
typecast_speech_composer_pause(composer, 5.0f);

TypecastComposerSettings second = {0};
second.voice_id = "tc_60e5426de8b95f1d3000d7b5";
second.output.audio_pitch = 2;
typecast_speech_composer_say(composer, "Nice to meet you", &second);
typecast_speech_composer_pause(composer, 2.0f);
typecast_speech_composer_say(composer, "How does the weather feel?", NULL);

TypecastTTSResponse* audio = typecast_speech_composer_generate(composer, TYPECAST_AUDIO_FORMAT_WAV);
/* write audio->audio_data / audio->audio_len to conversation.wav */
typecast_tts_response_free(audio);
typecast_speech_composer_destroy(composer);
```

### Voice Discovery (V2 API)

List and filter available voices with enhanced metadata:

```c
// Get all voices
TypecastVoicesResponse* voices = typecast_get_voices(client, NULL);

// Or filter by criteria
TypecastModel model = TYPECAST_MODEL_SSFM_V30;
TypecastGender gender = TYPECAST_GENDER_FEMALE;
TypecastAge age = TYPECAST_AGE_YOUNG_ADULT;

TypecastVoicesFilter filter = {0};
filter.model = &model;
filter.gender = &gender;
filter.age = &age;

TypecastVoicesResponse* filtered = typecast_get_voices(client, &filter);

// Display voice info
if (voices) {
    for (size_t i = 0; i < voices->count; i++) {
        TypecastVoice* v = &voices->voices[i];
        printf("ID: %s, Name: %s\n", v->voice_id, v->voice_name);
        printf("Gender: %d, Age: %d\n", v->gender, v->age);
        
        for (size_t j = 0; j < v->models_count; j++) {
            printf("Model: %s, Emotions: ", 
                   typecast_model_to_string(v->models[j].version));
            for (size_t k = 0; k < v->models[j].emotions_count; k++) {
                printf("%s ", v->models[j].emotions[k]);
            }
            printf("\n");
        }
        
        if (v->use_cases) {
            printf("Use cases: ");
            for (size_t k = 0; k < v->use_cases_count; k++) {
                printf("%s ", v->use_cases[k]);
            }
            printf("\n");
        }
    }
    typecast_voices_response_free(voices);
}
```

### Multilingual Content

The SDK supports 35+ languages with automatic language detection:

```c
// Auto-detect language (recommended - omit language field)
TypecastTTSRequest request = {0};
request.text = "こんにちは。お元気ですか。";
request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
request.model = TYPECAST_MODEL_SSFM_V30;
// language is NULL, so it will be auto-detected

TypecastTTSResponse* response = typecast_text_to_speech(client, &request);

// Or specify language explicitly using ISO 639-3 code
TypecastTTSRequest korean_request = {0};
korean_request.text = "안녕하세요. 반갑습니다.";
korean_request.voice_id = "tc_672c5f5ce59fac2a48faeaee";
korean_request.model = TYPECAST_MODEL_SSFM_V30;
korean_request.language = "kor";  // ISO 639-3 language code

TypecastTTSResponse* korean_response = typecast_text_to_speech(client, &korean_request);
```

### Streaming

Stream audio chunks in real-time for low-latency playback:

```c
// Extract raw PCM for real-time playback (skip 44-byte WAV header)
static int g_first = 1;

static int on_chunk(const uint8_t *data, size_t len, void *user_data) {
    const uint8_t *pcm = data;
    size_t pcm_len = len;

    if (g_first) {
        pcm += 44;       // Skip WAV header
        pcm_len -= 44;
        g_first = 0;
    }
    // pcm is raw 16-bit mono PCM at 32000 Hz
    // Feed to your audio output (e.g. PortAudio, ALSA)
    play_audio(pcm, pcm_len);  // your playback function
    return 0;
}
```

<Note>
**WAV streaming format:** 32000 Hz, 16-bit, mono PCM. The first chunk includes a 44-byte WAV header (size = `0xFFFFFFFF`); subsequent chunks are raw PCM only. For MP3: 320 kbps, 44100 Hz, each chunk is independently decodable. Use `TYPECAST_OUTPUT_STREAM_DEFAULT()` for safe output defaults.
</Note>

## Timestamp TTS

`typecast_text_to_speech_with_timestamps()` wraps `POST /v1/text-to-speech/with-timestamps` and returns the audio together with per-word and per-character alignment data - useful for karaoke highlights, subtitle generation, and lip-sync applications.

### Basic Usage

```c
#include "typecast.h"
#include <stdio.h>
#include <stdlib.h>

int main() {
    TypecastClient* client = typecast_client_create("YOUR_API_KEY");
    if (!client) return 1;

    TypecastTTSWithTimestampsRequest request = {0};
    request.text     = "Hello. How are you?";
    request.voice_id = "tc_60e5426de8b95f1d3000d7b5";
    request.model    = TYPECAST_MODEL_SSFM_V30;

    TypecastTTSWithTimestampsResponse* result =
        typecast_text_to_speech_with_timestamps(client, &request);

    if (result) {
        FILE* fp = fopen("output.wav", "wb");
        fwrite(result->audio_data, 1, result->audio_size, fp);
        fclose(fp);

        printf("Duration: %.3fs\n", result->audio_duration);

        for (size_t i = 0; i < result->word_count; i++) {
            printf("  [%.3fs – %.3fs] %s\n",
                result->words[i].start_time,
                result->words[i].end_time,
                result->words[i].text);
        }

        typecast_tts_with_timestamps_response_free(result);
    }

    typecast_client_destroy(client);
    return 0;
}
```

### Granularity

Set `request.granularity = TYPECAST_GRANULARITY_WORD` (default) or `TYPECAST_GRANULARITY_CHAR` to control the alignment unit.

```c
request.granularity = TYPECAST_GRANULARITY_CHAR;  /* required for jpn / zho */
```

### Subtitle Export

```c
// Export SRT (caller must free the returned string)
char* srt = typecast_tts_with_timestamps_to_srt(result);
FILE* fp = fopen("output.srt", "w");
fputs(srt, fp);
fclose(fp);
free(srt);

// Export WebVTT
char* vtt = typecast_tts_with_timestamps_to_vtt(result);
// ... same pattern as above
free(vtt);
```

<Note>
**Japanese / Chinese:** Word-level segmentation is not meaningful for languages without whitespace delimiters (jpn, zho). Use `TYPECAST_GRANULARITY_CHAR` for these languages to get character-level alignment.
</Note>

## Instant Voice Cloning

Clone a custom voice from a short audio sample, then pass the returned `uc_` voice ID directly to TTS.

```c
TypecastCustomVoice voice;
TypecastErrorCode rc = typecast_clone_voice(
    client,
    audio_bytes,
    audio_len,
    "sample.wav",
    "My Voice",
    "ssfm-v30",
    &voice
);

if (rc == TYPECAST_OK) {
    TypecastTTSRequest request = {0};
    request.voice_id = voice.voice_id;
    request.text = "Hello from my cloned voice!";
    request.model = TYPECAST_MODEL_SSFM_V30;

    TypecastTTSResponse* response = typecast_text_to_speech(client, &request);
    if (response) {
        typecast_tts_response_free(response);
    }

    typecast_delete_voice(client, voice.voice_id);
}
```

<Warning>
Voice cloning audio must be **25 MB or smaller**, the audio duration must be **5-150 seconds**, and the custom voice name must be **1-30 characters**.
</Warning>

## Supported Languages

The SDK supports 35+ languages with automatic language detection:

| Code | Language | Code | Language | Code | Language |
|------|----------|------|----------|------|----------|
| `eng` | English | `jpn` | Japanese | `ukr` | Ukrainian |
| `kor` | Korean | `ell` | Greek | `ind` | Indonesian |
| `spa` | Spanish | `tam` | Tamil | `dan` | Danish |
| `deu` | German | `tgl` | Tagalog | `swe` | Swedish |
| `fra` | French | `fin` | Finnish | `msa` | Malay |
| `ita` | Italian | `zho` | Chinese | `ces` | Czech |
| `pol` | Polish | `slk` | Slovak | `por` | Portuguese |
| `nld` | Dutch | `ara` | Arabic | `bul` | Bulgarian |
| `rus` | Russian | `hrv` | Croatian | `ron` | Romanian |
| `ben` | Bengali | `hin` | Hindi | `hun` | Hungarian |
| `nan` | Hokkien | `nor` | Norwegian | `pan` | Punjabi |
| `tha` | Thai | `tur` | Turkish | `vie` | Vietnamese |
| `yue` | Cantonese | | | | |

<Info>
If not specified, the language will be automatically detected from the input text.
</Info>

## Error Handling

The SDK provides specific error codes for handling API errors:

```c
#include "typecast.h"

TypecastTTSResponse* response = typecast_text_to_speech(client, &request);

if (!response) {
    const TypecastError* err = typecast_client_get_error(client);
    
    switch (err->code) {
        case TYPECAST_ERROR_UNAUTHORIZED:
            // 401: Invalid API key
            fprintf(stderr, "Invalid API key: %s\n", err->message);
            break;
        case TYPECAST_ERROR_PAYMENT_REQUIRED:
            // 402: Insufficient credits
            fprintf(stderr, "Insufficient credits: %s\n", err->message);
            break;
        case TYPECAST_ERROR_NOT_FOUND:
            // 404: Resource not found
            fprintf(stderr, "Voice not found: %s\n", err->message);
            break;
        case TYPECAST_ERROR_UNPROCESSABLE_ENTITY:
            // 422: Validation error
            fprintf(stderr, "Validation error: %s\n", err->message);
            break;
        case TYPECAST_ERROR_RATE_LIMIT:
            // 429: Rate limit exceeded
            fprintf(stderr, "Rate limit exceeded - please retry later\n");
            break;
        case TYPECAST_ERROR_INTERNAL_SERVER:
            // 500: Server error
            fprintf(stderr, "Server error: %s\n", err->message);
            break;
        default:
            fprintf(stderr, "API error (%d): %s\n", err->code, err->message);
            break;
    }
}
```

### Error Codes

| Error Code | Value | Description |
|-----------|-------|-------------|
| `TYPECAST_OK` | 0 | Success |
| `TYPECAST_ERROR_INVALID_PARAM` | -1 | Invalid request parameters |
| `TYPECAST_ERROR_OUT_OF_MEMORY` | -2 | Memory allocation failed |
| `TYPECAST_ERROR_CURL_INIT` | -3 | Failed to initialize libcurl |
| `TYPECAST_ERROR_NETWORK` | -4 | Network error |
| `TYPECAST_ERROR_JSON_PARSE` | -5 | JSON parsing error |
| `TYPECAST_ERROR_BAD_REQUEST` | 400 | Invalid request |
| `TYPECAST_ERROR_UNAUTHORIZED` | 401 | Invalid or missing API key |
| `TYPECAST_ERROR_PAYMENT_REQUIRED` | 402 | Insufficient credits |
| `TYPECAST_ERROR_NOT_FOUND` | 404 | Resource not found |
| `TYPECAST_ERROR_UNPROCESSABLE_ENTITY` | 422 | Validation error |
| `TYPECAST_ERROR_RATE_LIMIT` | 429 | Rate limit exceeded |
| `TYPECAST_ERROR_INTERNAL_SERVER` | 500 | Server error |

## C++ Wrapper

For C++ projects, enable the optional C++ wrapper for a more idiomatic interface:

```cpp
#define TYPECAST_CPP_WRAPPER
#include "typecast.h"

#include <fstream>
#include <iostream>

int main() {
    try {
        // Initialize client
        typecast::Client client("YOUR_API_KEY");

        // Convert text to speech
        typecast::TTSRequest request;
        request.text = "Hello there! I'm your friendly text-to-speech agent.";
        request.voiceId = "tc_672c5f5ce59fac2a48faeaee";
        request.model = typecast::Model::SSFM_V30;
        request.language = "eng";

        auto response = client.textToSpeech(request);

        // Save audio file
        std::ofstream file("output.wav", std::ios::binary);
        file.write(reinterpret_cast<const char*>(response.audioData.data()), 
                   response.audioData.size());

        std::cout << "Audio saved! Duration: " << response.duration << "s\n";

    } catch (const typecast::TypecastException& e) {
        std::cerr << "Error (" << e.code << "): " << e.what() << "\n";
        return 1;
    }

    return 0;
}
```

## Platform Support

The SDK has been verified through automated E2E testing on the following platforms:

| Platform | Architecture | glibc | C Standard | Status |
|----------|--------------|-------|------------|--------|
| **CentOS 6.9** | x86_64 | 2.12 | C99 | Verified |
| **CentOS 7** | x86_64 | 2.17 | C11 | Verified |
| **Amazon Linux 2** | x86_64 | 2.26 | C11 | Verified |
| **Ubuntu 20.04 LTS** | x86_64 | 2.31 | C11 | Verified |
| **Debian Bullseye** | x86_64 | 2.31 | C11 | Verified |
| **Windows** | x64 | N/A | C11 | Verified |
| **macOS** | x86_64 / arm64 | N/A | C11 | Verified |

## Embedded Systems

This SDK can be integrated into embedded systems with network connectivity.

### Cross-Compilation

<Tabs>
  <Tab title="ARM Linux (32-bit)">
    ```bash
    mkdir build-arm && cd build-arm
    cmake .. \
        -DCMAKE_TOOLCHAIN_FILE=../cmake/arm-linux-gnueabihf.cmake \
        -DTYPECAST_BUILD_STATIC=ON \
        -DTYPECAST_BUILD_SHARED=OFF \
        -DCMAKE_BUILD_TYPE=MinSizeRel
    cmake --build .
    ```
  </Tab>

  <Tab title="ARM64 Linux">
    ```bash
    mkdir build-arm64 && cd build-arm64
    cmake .. \
        -DCMAKE_SYSTEM_NAME=Linux \
        -DCMAKE_SYSTEM_PROCESSOR=aarch64 \
        -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc \
        -DTYPECAST_BUILD_STATIC=ON \
        -DTYPECAST_BUILD_SHARED=OFF \
        -DCMAKE_BUILD_TYPE=MinSizeRel
    cmake --build .
    ```
  </Tab>
</Tabs>

### Memory Requirements

| Component | Approximate Size |
|-----------|------------------|
| Static library (MinSizeRel) | ~50 KB |
| Runtime heap per client | ~8 KB |
| TTS response buffer | Variable (audio size) |
| JSON parsing buffer | ~4 KB |

## Unreal Engine Integration

This SDK is designed for seamless integration with Unreal Engine 4.27+ and Unreal Engine 5.x.

<Steps>
  <Step title="Build the SDK">
    Build as a static library:

    ```bash
    mkdir build && cd build
    cmake .. -DTYPECAST_BUILD_STATIC=ON -DTYPECAST_BUILD_SHARED=OFF -DCMAKE_BUILD_TYPE=Release
    cmake --build . --config Release
    ```
  </Step>

  <Step title="Create Plugin Structure">
    Create a plugin in your Unreal project:

    ```
    Plugins/
    └── TypecastTTS/
        ├── Source/TypecastTTS/
        │   ├── Private/
        │   ├── Public/
        │   └── ThirdParty/Typecast/
        │       ├── include/typecast.h
        │       └── lib/Win64/typecast_static.lib
        ├── TypecastTTS.uplugin
        └── TypecastTTS.Build.cs
    ```
  </Step>

  <Step title="Configure Build.cs">
    Add library linking to your `Build.cs`:

    ```csharp
    // Add include path
    PublicIncludePaths.Add(Path.Combine(ThirdPartyPath, "include"));
    PublicDefinitions.Add("TYPECAST_STATIC");

    // Link static library (platform-specific)
    if (Target.Platform == UnrealTargetPlatform.Win64)
    {
        PublicAdditionalLibraries.Add(
            Path.Combine(LibPath, "Win64", "typecast_static.lib"));
        AddEngineThirdPartyPrivateStaticDependencies(Target, "libcurl");
    }
    ```
  </Step>
</Steps>

<Info>
For complete Unreal Engine integration guide including Blueprint support and audio playback, see the [README](https://github.com/neosapience/typecast-sdk/tree/main/typecast-c) in the SDK repository.
</Info>

## API Reference

### Client Functions

| Function | Description |
|----------|-------------|
| `typecast_client_create(api_key)` | Create client with API key |
| `typecast_client_create_with_host(api_key, host)` | Create client with custom host |
| `typecast_client_destroy(client)` | Destroy client and free resources |
| `typecast_client_get_error(client)` | Get last error information |

### Text-to-Speech Functions

| Function | Description |
|----------|-------------|
| `typecast_text_to_speech(client, request)` | Convert text to speech audio |
| `typecast_generate_to_file(client, path, request)` | Generate speech and save it directly to a local file |
| `typecast_tts_response_free(response)` | Free TTS response memory |

### Voice Functions

| Function | Description |
|----------|-------------|
| `typecast_get_voices(client, filter)` | Get available voices (optionally filtered) |
| `typecast_get_voice(client, voice_id)` | Get a specific voice by ID |
| `typecast_clone_voice(client, audio, audio_len, filename, name, model, out)` | Create a custom voice via instant cloning |
| `typecast_delete_voice(client, voice_id)` | Delete a custom cloned voice |
| `typecast_voices_response_free(response)` | Free voices response memory |
| `typecast_voice_free(voice)` | Free single voice memory |

### Utility Functions

| Function | Description |
|----------|-------------|
| `typecast_version()` | Get library version string |
| `typecast_model_to_string(model)` | Convert model enum to string |
| `typecast_emotion_to_string(emotion)` | Convert emotion enum to string |
| `typecast_audio_format_to_string(format)` | Convert format enum to string |
| `typecast_error_message(code)` | Get error message for error code |

### TypecastTTSRequest Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `text` | `const char*` | ✓ | Text to synthesize (max 2000 chars) |
| `voice_id` | `const char*` | ✓ | Voice ID (format: `tc_*` or `uc_*`) |
| `model` | `TypecastModel` | ✓ | TTS model (`SSFM_V21` or `SSFM_V30`) |
| `language` | `const char*` | | ISO 639-3 code (auto-detected if NULL) |
| `prompt` | `TypecastPrompt*` | | Emotion settings |
| `output` | `TypecastOutput*` | | Audio output settings |

### TypecastTTSResponse Fields

| Field | Type | Description |
|-------|------|-------------|
| `audio_data` | `uint8_t*` | Generated audio data |
| `audio_size` | `size_t` | Size of audio data in bytes |
| `duration` | `float` | Audio duration in seconds |
| `format` | `TypecastAudioFormat` | Audio format (wav or mp3) |
