write me c# code to inference with this uvicorn server

import os
import torch
import torchaudio
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import JSONResponse, StreamingResponse
from pydantic import BaseModel
from typing import Optional, List
from zonos.model import Zonos, DEFAULT_BACKBONE_CLS as ZonosBackbone
from zonos.conditioning import make_cond_dict, supported_language_codes
from zonos.utils import DEFAULT_DEVICE as device

CURRENT_MODEL_TYPE = None
CURRENT_MODEL = None

SPEAKER_EMBEDDING = None
SPEAKER_AUDIO_PATH = None


# Define a request model for audio generation
class GenerateAudioRequest(BaseModel):
    model_choice: str
    text: str
    language: str
    speaker_audio: Optional[str] = None
    prefix_audio: Optional[str] = None
    emotions: List[float]
    vq_single: float
    fmax: float
    pitch_std: float
    speaking_rate: float
    dnsmos_ovrl: float
    speaker_noised: bool
    cfg_scale: float
    min_p: float
    seed: int
    randomize_seed: bool
    unconditional_keys: List[str]


# Initialize FastAPI
app = FastAPI()


def load_model_if_needed(model_choice: str):
    global CURRENT_MODEL_TYPE, CURRENT_MODEL
    if CURRENT_MODEL_TYPE != model_choice:
        if CURRENT_MODEL is not None:
            del CURRENT_MODEL
            torch.cuda.empty_cache()
        print(f"Loading {model_choice} model...")
        CURRENT_MODEL = Zonos.from_pretrained(model_choice, device=device)
        CURRENT_MODEL.requires_grad_(False).eval()
        CURRENT_MODEL_TYPE = model_choice
        print(f"{model_choice} model loaded successfully!")
    return CURRENT_MODEL


def generate_audio(request: GenerateAudioRequest):
    selected_model = load_model_if_needed(request.model_choice)

    global SPEAKER_AUDIO_PATH, SPEAKER_EMBEDDING

    # Manage random seed
    seed = request.seed
    if request.randomize_seed:
        seed = torch.randint(0, 2 ** 32 - 1, (1,)).item()
    torch.manual_seed(seed)

    # Process speaker audio embedding
    if request.speaker_audio is not None:
        if request.speaker_audio != SPEAKER_AUDIO_PATH:
            print("Recomputed speaker embedding")
            wav, sr = torchaudio.load(request.speaker_audio)
            SPEAKER_EMBEDDING = selected_model.make_speaker_embedding(wav, sr)
            SPEAKER_EMBEDDING = SPEAKER_EMBEDDING.to(device, dtype=torch.bfloat16)
            SPEAKER_AUDIO_PATH = request.speaker_audio

    # Process prefix audio
    audio_prefix_codes = None
    if request.prefix_audio is not None:
        wav_prefix, sr_prefix = torchaudio.load(request.prefix_audio)
        wav_prefix = wav_prefix.mean(0, keepdim=True)
        wav_prefix = selected_model.autoencoder.preprocess(wav_prefix, sr_prefix)
        wav_prefix = wav_prefix.to(device, dtype=torch.float32)
        audio_prefix_codes = selected_model.autoencoder.encode(wav_prefix.unsqueeze(0))

    # Convert emotion values to tensor
    emotion_tensor = torch.tensor(request.emotions, device=device)

    vq_tensor = torch.tensor([request.vq_single] * 8, device=device).unsqueeze(0)

    cond_dict = make_cond_dict(
        text=request.text,
        language=request.language,
        speaker=SPEAKER_EMBEDDING,
        emotion=emotion_tensor,
        vqscore_8=vq_tensor,
        fmax=request.fmax,
        pitch_std=request.pitch_std,
        speaking_rate=request.speaking_rate,
        dnsmos_ovrl=request.dnsmos_ovrl,
        speaker_noised=request.speaker_noised,
        device=device,
        unconditional_keys=request.unconditional_keys,
    )
    conditioning = selected_model.prepare_conditioning(cond_dict)

    max_new_tokens = 86 * 30
    codes = selected_model.generate(
        prefix_conditioning=conditioning,
        audio_prefix_codes=audio_prefix_codes,
        max_new_tokens=max_new_tokens,
        cfg_scale=request.cfg_scale,
        batch_size=1,
        sampling_params=dict(min_p=request.min_p),
    )

    wav_out = selected_model.autoencoder.decode(codes).cpu().detach()
    sr_out = selected_model.autoencoder.sampling_rate
    if wav_out.dim() == 2 and wav_out.size(0) > 1:
        wav_out = wav_out[0:1, :]
        
    return {"sample_rate": sr_out, "audio": wav_out.squeeze().numpy().tolist(), "seed": seed}


@app.post("/generate_audio")
async def create_audio(request: GenerateAudioRequest):
    result = generate_audio(request)
    return JSONResponse(content=result)


@app.get("/supported_languages")
async def obtain_languages():
    return {"supported_languages": supported_language_codes}


if __name__ == "__main__":
    import uvicorn
    host = os.getenv("SERVER_NAME", "0.0.0.0")
    port = int(os.getenv("SERVER_PORT", 8000))
    uvicorn.run(app, host=host, port=port)