hi please fix my unity editor window script there's nothing wrong with it other than the fact that the logo is not centered within the window correctly. Please fix and provide full script ty.

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;

public class SeedVCWindow : EditorWindow
{
    private Texture2D logo;

    // Parameters (matching AudioConverter class)
    private string serverUrl = "http://localhost:8000/convert";
    private int qualityValue = 10;

    // Audio clips for input
    private AudioClip sourceClip;
    private AudioClip referenceClip;

    // Selected folder to save result
    private DefaultAsset saveFolderAsset;
    private string saveFolderPath = "Assets/";

    // Status message
    private string statusMessage;
    private bool isConverting = false;

    // Playback
    private AudioClip convertedClip;
    private bool isPlaying = false;
    private Vector2 scrollPos;

    // --- Added for Recording ---
    private string[] micDevices;
    private int selectedMicIndex = 0;

    // Recording state
    private bool isRecordingSource = false;
    private bool isRecordingReference = false;

    private AudioClip recordingClipSource;
    private AudioClip recordingClipReference;

    // Max recording length in seconds
    private const int maxRecordingLength = 30;

    [MenuItem("Tools/Seed_VC")]
    private static void ShowWindow()
    {
        var window = GetWindow<SeedVCWindow>("Seed_VC");
        window.minSize = new Vector2(400, 600);
    }

    private void OnEnable()
    {
        // Load logo from Resources folder (Assets/Resources/seed_vc_logo.png)
        logo = Resources.Load<Texture2D>("seed_vc_logo");
        EditorApplication.update += EditorUpdate;

        // Get microphone devices
        micDevices = Microphone.devices;
        if (micDevices == null || micDevices.Length == 0)
        {
            micDevices = new string[] { "No Microphone Devices Found" };
            selectedMicIndex = 0;
        }
        else
        {
            selectedMicIndex = 0;
        }
    }

    private void OnDisable()
    {
        EditorApplication.update -= EditorUpdate;
        StopPlayback();
        StopRecordingSource();
        StopRecordingReference();
    }

    private void EditorUpdate()
    {
        if (isPlaying && !EditorApplication.isPlaying && !Application.isPlaying)
        {
            // Keep inspector repainting if audio is playing
            Repaint();
        }
    }

    private void OnGUI()
    {
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);

        GUILayout.Space(10);

        if (logo != null)
        {
            float maxWidth = position.width - 20; // 20 pixels padding for safety
            float aspectRatio = (float)logo.height / logo.width;
            float drawWidth = Mathf.Min(logo.width, maxWidth);
            float drawHeight = drawWidth * aspectRatio;

            var rect = GUILayoutUtility.GetRect(drawWidth, drawHeight, GUILayout.ExpandWidth(false));
            GUI.DrawTexture(rect, logo, ScaleMode.ScaleToFit);
        }
        else
        {
            EditorGUILayout.HelpBox("Logo not found in Resources as 'seed_vc_logo'. Please add a PNG named 'seed_vc_logo' to Assets/Resources.", MessageType.Warning);
        }

        GUILayout.Space(10);

        EditorGUILayout.LabelField("Server URL:", EditorStyles.boldLabel);
        serverUrl = EditorGUILayout.TextField(serverUrl);

        EditorGUILayout.LabelField("Quality Value (diffusion_steps):", EditorStyles.boldLabel);
        qualityValue = EditorGUILayout.IntSlider(qualityValue, 1, 100);

        GUILayout.Space(10);

        // --- Microphone Selection ---
        EditorGUILayout.LabelField("Select Recording Device (Microphone):", EditorStyles.boldLabel);

        if (micDevices.Length == 0 || micDevices[0] == "No Microphone Devices Found")
        {
            EditorGUILayout.HelpBox("No microphone devices found on this machine.", MessageType.Warning);
        }
        else
        {
            int newSelectedIndex = EditorGUILayout.Popup(selectedMicIndex, micDevices);
            if (newSelectedIndex != selectedMicIndex)
            {
                selectedMicIndex = newSelectedIndex;
                // Stop any ongoing recordings when device changes
                if (isRecordingSource) StopRecordingSource();
                if (isRecordingReference) StopRecordingReference();
            }
        }

        GUILayout.Space(10);

        EditorGUILayout.LabelField("Source Audio Clip:", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();
        sourceClip = (AudioClip)EditorGUILayout.ObjectField(sourceClip, typeof(AudioClip), false);

        if (micDevices.Length > 0 && micDevices[0] != "No Microphone Devices Found")
        {
            if (!isRecordingSource)
            {
                if (GUILayout.Button("Record Source", GUILayout.Width(120)))
                {
                    StartRecordingSource();
                }
            }
            else
            {
                if (GUILayout.Button("Stop Recording", GUILayout.Width(120)))
                {
                    StopRecordingSource();
                }
            }
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.LabelField("Reference Audio Clip:", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();
        referenceClip = (AudioClip)EditorGUILayout.ObjectField(referenceClip, typeof(AudioClip), false);

        if (micDevices.Length > 0 && micDevices[0] != "No Microphone Devices Found")
        {
            if (!isRecordingReference)
            {
                if (GUILayout.Button("Record Reference", GUILayout.Width(120)))
                {
                    StartRecordingReference();
                }
            }
            else
            {
                if (GUILayout.Button("Stop Recording", GUILayout.Width(120)))
                {
                    StopRecordingReference();
                }
            }
        }
        EditorGUILayout.EndHorizontal();

        GUILayout.Space(10);

        EditorGUILayout.LabelField("Save Folder:", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();

        saveFolderAsset = (DefaultAsset)EditorGUILayout.ObjectField(saveFolderAsset, typeof(DefaultAsset), false);
        if (GUILayout.Button("Select Folder", GUILayout.Width(100)))
        {
            string selectedPath = EditorUtility.OpenFolderPanel("Select Save Folder", Application.dataPath, "");
            if (!string.IsNullOrEmpty(selectedPath))
            {
                // Convert absolute path to relative Unity project path
                if (selectedPath.StartsWith(Application.dataPath))
                {
                    saveFolderPath = "Assets" + selectedPath.Substring(Application.dataPath.Length);
                    saveFolderAsset = AssetDatabase.LoadAssetAtPath<DefaultAsset>(saveFolderPath);
                }
                else
                {
                    EditorUtility.DisplayDialog("Invalid Folder", "Selected folder must be inside the Assets directory.", "OK");
                }
            }
        }
        EditorGUILayout.EndHorizontal();

        GUILayout.Space(15);

        GUI.enabled = !isConverting;
        if (GUILayout.Button("CONVERT", GUILayout.Height(40)))
        {
            if (!ValidateInputs())
                return;

            _ = ConvertAudioFiles(); // Fire & forget async task
        }
        GUI.enabled = true;

        GUILayout.Space(10);

        EditorGUILayout.HelpBox(statusMessage, MessageType.Info);

        GUILayout.Space(10);

        if (convertedClip != null)
        {
            EditorGUILayout.LabelField("Converted Audio Playback:", EditorStyles.boldLabel);

            EditorGUILayout.BeginHorizontal();

            if (!isPlaying)
            {
                if (GUILayout.Button("Play"))
                {
                    PlayConvertedClip();
                }
            }
            else
            {
                if (GUILayout.Button("Stop"))
                {
                    StopPlayback();
                }
            }

            if (GUILayout.Button("Ping Asset", GUILayout.Width(100)))
            {
                string path = AssetDatabase.GetAssetPath(convertedClip);
                if (!string.IsNullOrEmpty(path))
                {
                    UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath<AudioClip>(path);
                    if (obj != null)
                    {
                        EditorGUIUtility.PingObject(obj);
                    }
                }
            }

            EditorGUILayout.EndHorizontal();
        }

        EditorGUILayout.EndScrollView();
    }

    private bool ValidateInputs()
    {
        if (string.IsNullOrWhiteSpace(serverUrl))
        {
            statusMessage = "Server URL cannot be empty.";
            return false;
        }

        if (qualityValue < 1)
        {
            statusMessage = "Quality value must be greater than 0.";
            return false;
        }

        if (sourceClip == null)
        {
            statusMessage = "Please assign a Source Audio Clip.";
            return false;
        }

        if (referenceClip == null)
        {
            statusMessage = "Please assign a Reference Audio Clip.";
            return false;
        }

        if (saveFolderAsset == null || string.IsNullOrEmpty(saveFolderPath))
        {
            statusMessage = "Please select a save folder inside the Assets directory.";
            return false;
        }

        return true;
    }

    private async Task ConvertAudioFiles()
    {
        isConverting = true;
        statusMessage = "Reading audio clips and preparing data...";
        Repaint();

        convertedClip = null;
        StopPlayback();

        try
        {
            // Convert AudioClips to WAV byte arrays
            byte[] sourceWavData = AudioClipToWav(sourceClip);
            byte[] referenceWavData = AudioClipToWav(referenceClip);

            if (sourceWavData == null || referenceWavData == null)
            {
                statusMessage = "Failed to convert AudioClips to WAV bytes.";
                isConverting = false;
                Repaint();
                return;
            }

            statusMessage = "Sending data to server...";
            Repaint();

            var base64FileData = await UploadAudioAndConvert(sourceWavData, referenceWavData);

            if (!string.IsNullOrEmpty(base64FileData))
            {
                statusMessage = $"Conversion succeeded, saving the file...";
                Repaint();

                bool saved = SaveFileToAssetFolder(base64FileData, out AudioClip loadedClip);

                if (saved)
                {
                    convertedClip = loadedClip;
                    statusMessage = "File saved successfully. You can play it back below.";
                    // Ping the asset automatically after saving
                    EditorGUIUtility.PingObject(convertedClip);
                }
                else
                {
                    statusMessage = "Failed to save the file as an asset.";
                }
            }
            else
            {
                statusMessage = "Conversion failed or no file returned.";
            }
        }
        catch (Exception ex)
        {
            Debug.LogException(ex);
            statusMessage = $"An error occurred: {ex.Message}";
        }
        finally
        {
            isConverting = false;
            Repaint();
        }
    }

    private async Task<string> UploadAudioAndConvert(byte[] sourceAudioBytes, byte[] referenceAudioBytes)
    {
        List<IMultipartFormSection> formData = new List<IMultipartFormSection>
        {
            new MultipartFormFileSection("source_file", sourceAudioBytes, "source.wav", "audio/wav"),
            new MultipartFormFileSection("reference_file", referenceAudioBytes, "reference.wav", "audio/wav"),

            // Server parameters:
            new MultipartFormDataSection("diffusion_steps", qualityValue.ToString()),
            new MultipartFormDataSection("length_adjust", "1.0"),
            new MultipartFormDataSection("inference_cfg_rate", "0.7"),
            new MultipartFormDataSection("auto_f0_adjust", "true"),
            new MultipartFormDataSection("pitch_shift", "0")
        };

        using (UnityWebRequest request = UnityWebRequest.Post(serverUrl, formData))
        {
            var operation = request.SendWebRequest();

            while (!operation.isDone)
                await Task.Yield();

#if UNITY_2020_1_OR_NEWER
            if (request.result != UnityWebRequest.Result.Success)
#else
            if (request.isNetworkError || request.isHttpError)
#endif
            {
                statusMessage = $"Server error: {request.error}";
                return null;
            }

            var textResult = request.downloadHandler.text;
            if (string.IsNullOrWhiteSpace(textResult))
            {
                statusMessage = "Server returned an empty response.";
                return null;
            }

            try
            {
                ConversionResponse response = JsonUtility.FromJson<ConversionResponse>(textResult);
                string filePath = response.windows_path ?? response.file_path;

                if (string.IsNullOrEmpty(filePath))
                {
                    statusMessage = "Server response does not contain a valid file path.";
                    return null;
                }

                // Read the returned file bytes, assuming server returns a path accessible on local machine or network
                if (!File.Exists(filePath))
                {
                    statusMessage = $"Returned file does not exist on disk: {filePath}";
                    return null;
                }

                byte[] convertedFileBytes = File.ReadAllBytes(filePath);

                // Return this byte array as Base64 string for saving later
                return Convert.ToBase64String(convertedFileBytes);
            }
            catch (Exception ex)
            {
                statusMessage = "Failed to parse server response: " + ex.Message;
                return null;
            }
        }
    }

    private bool SaveFileToAssetFolder(string base64FileData, out AudioClip loadedClip)
    {
        loadedClip = null;
        try
        {
            byte[] fileBytes = Convert.FromBase64String(base64FileData);

            string fileName = $"converted_{DateTime.Now:yyyyMMdd_HHmmss}.wav";

            string fullPath = Path.Combine(saveFolderPath, fileName);

            // Convert to absolute path for writing file
            string absolutePath = Path.Combine(Application.dataPath.Substring(0, Application.dataPath.Length - 6), fullPath);

            File.WriteAllBytes(absolutePath, fileBytes);

            // Refresh AssetDatabase so the file shows up
            AssetDatabase.ImportAsset(fullPath, ImportAssetOptions.ForceUpdate);

            // Load the imported AudioClip asset
            loadedClip = AssetDatabase.LoadAssetAtPath<AudioClip>(fullPath);

            if (loadedClip == null)
            {
                Debug.LogWarning("Saved file but failed to load the AudioClip asset after import.");
            }

            return true;
        }
        catch (Exception ex)
        {
            Debug.LogError("Failed to save file: " + ex);
            return false;
        }
    }

    private void PlayConvertedClip()
    {
        if (convertedClip == null)
            return;

        if (isPlaying)
            StopPlayback();

        isPlaying = true;

        PlayClip(convertedClip);
    }

    private void StopPlayback()
    {
        if (!isPlaying)
            return;

        isPlaying = false;

        StopClip(convertedClip);
    }

    private static readonly Type audioUtilType = typeof(AudioImporter).Assembly.GetType("UnityEditor.AudioUtil");
    private static readonly System.Reflection.MethodInfo playClipMethod = audioUtilType?.GetMethod("PlayClip", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, new Type[] { typeof(AudioClip) }, null);
    private static readonly System.Reflection.MethodInfo stopClipMethod = audioUtilType?.GetMethod("StopClip", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, null, new Type[] { typeof(AudioClip) }, null);

    private static void PlayClip(AudioClip clip)
    {
        if (clip == null)
            return;

        playClipMethod?.Invoke(null, new object[] { clip });
    }

    private static void StopClip(AudioClip clip)
    {
        if (clip == null)
            return;

        stopClipMethod?.Invoke(null, new object[] { clip });
    }

    #region AudioClip to WAV conversion (unchanged)

    private byte[] AudioClipToWav(AudioClip clip)
    {
        if (clip == null)
            return null;

        float[] samples = new float[clip.samples * clip.channels];
        clip.GetData(samples, 0);

        byte[] wavData = ConvertAudioClipDataToWav(samples, clip.channels, clip.frequency);
        return wavData;
    }

    private byte[] ConvertAudioClipDataToWav(float[] samples, int channels, int sampleRate)
    {
        MemoryStream stream = new MemoryStream();
        BinaryWriter writer = new BinaryWriter(stream);

        int sampleCount = samples.Length;

        // RIFF header
        writer.Write(System.Text.Encoding.UTF8.GetBytes("RIFF"));
        writer.Write(36 + sampleCount * 2); // file size minus 8 bytes
        writer.Write(System.Text.Encoding.UTF8.GetBytes("WAVE"));

        // fmt chunk
        writer.Write(System.Text.Encoding.UTF8.GetBytes("fmt "));
        writer.Write(16); // Sub-chunk size
        writer.Write((short)1); // Audio format = PCM
        writer.Write((short)channels);
        writer.Write(sampleRate);
        writer.Write(sampleRate * channels * 2); // Byte rate
        writer.Write((short)(channels * 2)); // Block align
        writer.Write((short)16); // Bits per sample

        // data chunk
        writer.Write(System.Text.Encoding.UTF8.GetBytes("data"));
        writer.Write(sampleCount * 2); // Subchunk2Size

        // Write sample data
        short[] intData = new short[sampleCount];
        for (int i = 0; i < sampleCount; i++)
        {
            float sample = Mathf.Clamp(samples[i], -1f, 1f);
            intData[i] = (short)(sample * short.MaxValue);
        }

        for (int i = 0; i < intData.Length; i++)
        {
            writer.Write(intData[i]);
        }

        writer.Flush();
        writer.Close();

        return stream.ToArray();
    }

    #endregion

    #region Recording Methods

    private void StartRecordingSource()
    {
        if (micDevices == null || micDevices.Length == 0 || micDevices[0] == "No Microphone Devices Found")
        {
            statusMessage = "No microphone device available.";
            return;
        }

        if (isRecordingSource)
            return;

        if (Microphone.IsRecording(micDevices[selectedMicIndex]))
        {
            Microphone.End(micDevices[selectedMicIndex]);
        }

        recordingClipSource = Microphone.Start(micDevices[selectedMicIndex], false, maxRecordingLength, 44100);
        isRecordingSource = true;
        statusMessage = "Recording Source Audio...";
    }

    private void StopRecordingSource()
    {
        if (!isRecordingSource)
            return;

        Microphone.End(micDevices[selectedMicIndex]);

        // Get recorded data and create a new clip with exact length
        int samplePos = Microphone.GetPosition(micDevices[selectedMicIndex]);
        if (samplePos > 0 && recordingClipSource != null)
        {
            AudioClip newClip = AudioClip.Create("RecordedSource", samplePos, recordingClipSource.channels, recordingClipSource.frequency, false);
            float[] samples = new float[samplePos * recordingClipSource.channels];
            recordingClipSource.GetData(samples, 0);
            newClip.SetData(samples, 0);

            recordingClipSource = null;
            sourceClip = newClip;
            statusMessage = $"Source recording stopped. Length: {samplePos / (float)newClip.frequency:F2} seconds.";
        }
        else
        {
            statusMessage = "Source recording stopped but no audio data was captured.";
        }

        isRecordingSource = false;
    }

    private void StartRecordingReference()
    {
        if (micDevices == null || micDevices.Length == 0 || micDevices[0] == "No Microphone Devices Found")
        {
            statusMessage = "No microphone device available.";
            return;
        }

        if (isRecordingReference)
            return;

        if (Microphone.IsRecording(micDevices[selectedMicIndex]))
        {
            Microphone.End(micDevices[selectedMicIndex]);
        }

        recordingClipReference = Microphone.Start(micDevices[selectedMicIndex], false, maxRecordingLength, 44100);
        isRecordingReference = true;
        statusMessage = "Recording Reference Audio...";
    }

    private void StopRecordingReference()
    {
        if (!isRecordingReference)
            return;

        Microphone.End(micDevices[selectedMicIndex]);

        // Get recorded data and create a new clip with exact length
        int samplePos = Microphone.GetPosition(micDevices[selectedMicIndex]);
        if (samplePos > 0 && recordingClipReference != null)
        {
            AudioClip newClip = AudioClip.Create("RecordedReference", samplePos, recordingClipReference.channels, recordingClipReference.frequency, false);
            float[] samples = new float[samplePos * recordingClipReference.channels];
            recordingClipReference.GetData(samples, 0);
            newClip.SetData(samples, 0);

            recordingClipReference = null;
            referenceClip = newClip;
            statusMessage = $"Reference recording stopped. Length: {samplePos / (float)newClip.frequency:F2} seconds.";
        }
        else
        {
            statusMessage = "Reference recording stopped but no audio data was captured.";
        }

        isRecordingReference = false;
    }

    #endregion

    [Serializable]
    private class ConversionResponse
    {
        public string windows_path;
        public string file_path;
    }
}