I want to implement the following working code : async def main():
    # Initialize PyAudio
    p = pyaudio.PyAudio()
    stream = None
    
    # Create a container for the full audio data
    full_audio_data = bytearray()
    
    # Fetch audio data from edge_tts
    communicate = edge_tts.Communicate(TEXT, VOICE)
    async for chunk in communicate.stream():
        if chunk["type"] == "audio":
            # Directly append MP3 audio data
            full_audio_data.extend(chunk["data"])
        elif chunk["type"] == "WordBoundary":
            print(f"WordBoundary: {chunk}")
 
    if full_audio_data:
        # Convert the full audio data from MP3 to WAV once
        audio_segment = AudioSegment.from_file(BytesIO(full_audio_data), format="mp3")
        raw_data = audio_segment.raw_data
        
        # Open a single stream with the correct audio properties
        stream = p.open(
            format=p.get_format_from_width(audio_segment.sample_width),
            channels=audio_segment.channels,
            rate=audio_segment.frame_rate,
            output=True
        )

        # Stream the audio
        stream.write(raw_data)
    
        # Stop and close the stream
        stream.stop_stream()
        stream.close()
    
    # Terminate the PyAudio instance
    p.terminate()

in this code : 

    def __init__(self):        
        self.playback_queue = asyncio.Queue()
        pygame.mixer.init()

    async def generate_tts_audio(self, text_segments, voice, formatted_pitch):
        for segment in text_segments:
            unique_id = str(uuid.uuid4())
            file_name = f"{unique_id}.mp3"
            
            communicate = edge_tts.Communicate(segment, voice, pitch=formatted_pitch)
            await communicate.save(file_name)
            
            await self.playback_queue.put(file_name)

    async def playback_loop(self):
        index = 0
        pygame.mixer.init()  # Ensure pygame mixer is initialized
        while True:
            print(index)
            file_name = await self.playback_queue.get()
            sound = pygame.mixer.Sound(file_name)
            sound.play()

            length_ms = sound.get_length() * 1000
            if index == 0:
                # Calculate wait_time considering negative overlap for the first sound
                if WoWTTS.FIRST_OVERLAP_MS < 0:
                    # Play next sound x ms before the current sound ends
                    wait_time = length_ms + WoWTTS.FIRST_OVERLAP_MS
                else:
                    wait_time = length_ms - WoWTTS.FIRST_OVERLAP_MS
            else:
                # Calculate wait_time for subsequent sounds
                if WoWTTS.OVERLAP_MS < 0:
                    # Play next sound x ms before the current sound ends
                    wait_time = length_ms + WoWTTS.OVERLAP_MS
                else:
                    wait_time = length_ms - WoWTTS.OVERLAP_MS
            
            wait_time = max(wait_time, 0) / 1000.0  # Ensure wait_time is not negative and convert to seconds

            index += 1

            await asyncio.sleep(wait_time)

            os.remove(file_name)
            self.playback_queue.task_done()  # Mark the task as done after playback

    async def play(self, text_to_read, npc_sex, npc_race, pitch_index, voice_index, voice_effect):
        voice = self.get_voice_from_index_and_sex(voice_index, npc_sex)
        pitch = self.get_pitch_from_index_and_race(pitch_index, npc_race)
        formatted_pitch = self.format_pitch(pitch)
        
        # Split the text into segments of three words
        text_words = text_to_read.split()
        first_segment = " ".join(text_words[:1])
        remaining_text = " ".join(text_words[1:])

        # Split the remaining text by .!?
        text_segments = re.split(r'[.!?]', remaining_text)
        text_segments = [seg.strip() for seg in text_segments if seg.strip()]

        # Combine the first segment with the rest of the text segments
        text_segments.insert(0, first_segment)

        generator_task = asyncio.create_task(self.generate_tts_audio(text_segments, voice, formatted_pitch))
        playback_task = asyncio.create_task(self.playback_loop())

        await generator_task
        await self.playback_queue.join()  # Ensure all queued audio files have been played
        playback_task.cancel()  # Stop the playback loop

DO IT