def generate(
        self,
        text: str,
        ref_audio: Path = None,
        ref_text: str = None,
        gender: str = "male",
        pitch: float = 1.0,
        speed: float = 1.0,
        temperature: float = 0.8,
        top_k: float = 50,
        top_p: float = 0.95,
        max_tokens: int = 3000,
        verbose: bool = False,
        split_pattern: str = "\n",
        **kwargs,
    ) -> GenerationResult:
        """
        Performs inference to generate speech from text, incorporating prompt audio and/or text.

        Args:
            text (str): The text input to be converted to speech.
            ref_audio (Path): Path to the audio file used as a reference.
            ref_text (str, optional): Transcript of the reference audio.
            gender (str): female | male.
            pitch (str): very_low | low | moderate | high | very_high
            speed (str): very_low | low | moderate | high | very_high
            temperature (float, optional): Sampling temperature for controlling randomness. Default is 0.8.
            top_k (float, optional): Top-k sampling parameter. Default is 50.
            top_p (float, optional): Top-p (nucleus) sampling parameter. Default is 0.95.

        Returns:
            GenerationResult: Generated waveform as a tensor.
        """

        speed_factor = SPEED_MAP[speed]
        pitch_factor = PITCH_MAP[pitch]

        if ref_audio is not None:  # voice cloning
            gender = None

        text_splits = text.split(split_pattern)

        for text_split in text_splits:
            if gender is not None:
                prompt = self.process_prompt_control(
                    gender, pitch_factor, speed_factor, text_split
                )

            else:
                prompt, global_token_ids = self.process_prompt(
                    text_split, ref_audio, ref_text
                )

            inputs = self.tokenizer._tokenizer([prompt], return_tensors="pt")

            input_ids = mx.array(inputs.input_ids)

            sampler = make_sampler(temperature, top_p=top_p, top_k=top_k)
            logits_processors = make_logits_processors(
                kwargs.get("logit_bias", None),
                kwargs.get("repetition_penalty", 1.3),
                kwargs.get("repetition_context_size", 20),
            )

            time_start = time.time()

            generated_ids = []

            # Generate speech using the model
            for i, response in enumerate(
                tqdm(
                    stream_generate(
                        self.model,
                        tokenizer=self.tokenizer,
                        prompt=input_ids.squeeze(0),
                        max_tokens=max_tokens,
                        sampler=sampler,
                        logits_processors=logits_processors,
                    ),
                    total=max_tokens,
                    disable=not verbose,
                )
            ):
                next_token = mx.array([response.token])
                input_ids = mx.concatenate([input_ids, next_token[None, :]], axis=1)
                if i % 50 == 0:
                    mx.clear_cache()

                if next_token == 128258:
                    break

            time_end = time.time()
            # Trim the output tokens to remove the input tokens
            generated_ids = mx.array(
                [
                    output[len(input) :]
                    for input, output in zip(inputs.input_ids, input_ids)
                ]
            ).tolist()

            # Decode the generated tokens into text
            predicts = self.tokenizer._tokenizer.batch_decode(
                generated_ids, skip_special_tokens=True
            )[0]

            # Extract semantic token IDs from the generated text
            pred_semantic_ids = mx.array(
                [
                    int(token)
                    for token in re.findall(r"bicodec_semantic_(\d+)", predicts)
                ]
            )[None, ...]

            if gender is not None:
                global_token_ids = mx.array(
                    [
                        int(token)
                        for token in re.findall(r"bicodec_global_(\d+)", predicts)
                    ]
                )[None, ...]

            # Convert semantic tokens back to waveform
            audio = self._audio_tokenizer.detokenize(
                global_token_ids.astype(mx.int32),
                pred_semantic_ids.astype(mx.int32),
            )

            # Clear cache
            mx.clear_cache()

            audio_samples = len(audio)
            audio_duration_seconds = audio_samples / self.config.sample_rate

            # Format duration as HH:MM:SS.mmm
            duration_mins = int(audio_duration_seconds // 60)
            duration_secs = int(audio_duration_seconds % 60)
            duration_ms = int((audio_duration_seconds % 1) * 1000)
            duration_hours = int(audio_duration_seconds // 3600)
            duration_str = f"{duration_hours:02d}:{duration_mins:02d}:{duration_secs:02d}.{duration_ms:03d}"

            yield GenerationResult(
                audio=audio,
                sample_rate=self.config.sample_rate,
                samples=audio_samples,
                segment_idx=0,  # Default segment index
                token_count=len(pred_semantic_ids.squeeze()),
                audio_samples={
                    "samples": audio_samples,
                    "samples-per-sec": (
                        round(audio_samples / audio_duration_seconds, 2)
                        if audio_duration_seconds > 0
                        else 0
                    ),
                },
                audio_duration=duration_str,
                real_time_factor=(
                    audio_duration_seconds / (time_end - time_start)
                    if (time_end - time_start) > 0
                    else 0
                ),
                prompt={
                    "tokens": len(pred_semantic_ids.squeeze()),
                    "tokens-per-sec": (
                        round(
                            len(pred_semantic_ids.squeeze()) / audio_duration_seconds, 2
                        )
                        if audio_duration_seconds > 0
                        else 0
                    ),
                },
                processing_time_seconds=time_end - time_start,
                peak_memory_usage=mx.get_peak_memory() / 1e9,
            )

            # Clear cache after each segment to avoid memory leaks
            mx.clear_cache()

        Performs inference to generate speech from text, incorporating prompt audio and/or text.

        Args:
            text (str): The text input to be converted to speech.
            ref_audio (Path): Path to the audio file used as a reference.
            ref_text (str, optional): Transcript of the reference audio.
            gender (str): female | male.
            pitch (str): very_low | low | moderate | high | very_high
            speed (str): very_low | low | moderate | high | very_high
            temperature (float, optional): Sampling temperature for controlling randomness. Default is 0.8.
            top_k (float, optional): Top-k sampling parameter. Default is 50.
            top_p (float, optional): Top-p (nucleus) sampling parameter. Default is 0.95.

        Returns:
            GenerationResult: Generated waveform as a tensor.
        
mlx_audio/tts/models/spark/spark.py