Monday, June 2, 2025

TOO IMPORTANT CODE TO MERGE FREQUENCY WISE WAV FILES GTAMPS ALSO

 


namespace SAAN_FRESH___RAW_NON_APIS_WAVES_TO_SHRUTIES_COPIER_GPTS

{







    public class SwaralipiConcatenator_ResampleAware

    {

        public static void SwaralipiConcatenator___Main(string swaralipiFile)

        {

            string wavFolder = Path.GetDirectoryName(swaralipiFile);

            int outputSampleRate = 8000;

            string outputStereo = swaralipiFile + "_(yesssss)_merged_trimmed_RESAMPLED_8000_stereo.wav";

            string outputMono = swaralipiFile + "_(yesssss)_merged_trimmed_RESAMPLED_8000_mono.wav";


            var lines = File.ReadAllLines(swaralipiFile)

                            .Where(l => !string.IsNullOrWhiteSpace(l)).ToList();


            var allSegments = new List<float>();


            foreach (var line in lines)

            {

                var parts = line.Split(new[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries);

                if (parts.Length < 2) continue;


                string symbol = parts[0].Trim()

                                      .Replace(".", "_DOT_")

                                      .Replace("-", "dash")

                                      .Replace("#", "hash");


                if (!int.TryParse(parts[1], out int durationMs)) continue;


                string wavPath = Path.Combine(wavFolder, symbol + ".wav");

                float[] originalSamples = ReadWavMonoAsFloats(wavPath, out int originalSampleRate);


                // Step 1: Resample from originalSampleRate → outputSampleRate

                float[] resampled = ResampleToRate(originalSamples, originalSampleRate, outputSampleRate);


                // Step 2: Extract only as many samples as needed for desired duration

                int neededSamples = (int)((durationMs / 1000.0) * outputSampleRate);

                neededSamples = Math.Min(neededSamples, resampled.Length);


                float[] trimmed = new float[neededSamples];

                Array.Copy(resampled, trimmed, neededSamples);


                allSegments.AddRange(trimmed);

            }


            float[] final = allSegments.ToArray();


            SaveWav(outputStereo, final, outputSampleRate, 2);

            SaveWav(outputMono, final, outputSampleRate, 1);


            Console.WriteLine("Done writing merged WAV with preserved pitches.");

            System.Windows.Forms.MessageBox.Show("Done writing WAV:\n" + outputStereo + "\n" + outputMono);

        }


        public static float[] ResampleToRate(float[] input, int fromRate, int toRate)

        {

            if (fromRate == toRate) return input;


            int newLength = (int)(input.Length * (toRate / (double)fromRate));

            float[] result = new float[newLength];


            double step = (double)(input.Length - 1) / (newLength - 1);

            for (int i = 0; i < newLength; i++)

            {

                double idx = i * step;

                int index = (int)idx;

                double frac = idx - index;


                float interpolated = (index + 1 < input.Length)

                    ? (float)((1 - frac) * input[index] + frac * input[index + 1])

                    : input[index];


                result[i] = interpolated;

            }


            return result;

        }


        static float[] ReadWavMonoAsFloats(string path, out int sampleRate)

        {

            using (BinaryReader br = new BinaryReader(File.OpenRead(path)))

            {

                string riff = new string(br.ReadChars(4));

                br.ReadInt32();

                string wave = new string(br.ReadChars(4));


                int channels = 1;

                sampleRate = 8000;

                int bitsPerSample = 16;


                while (true)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSize = br.ReadInt32();


                    if (chunkID == "fmt ")

                    {

                        br.ReadInt16(); // format

                        channels = br.ReadInt16();

                        sampleRate = br.ReadInt32();

                        br.ReadInt32();

                        br.ReadInt16();

                        bitsPerSample = br.ReadInt16();

                        if (chunkSize > 16) br.ReadBytes(chunkSize - 16);

                        break;

                    }

                    else br.ReadBytes(chunkSize);

                }


                while (true)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSize = br.ReadInt32();


                    if (chunkID == "data")

                    {

                        int bytesPerSample = bitsPerSample / 8;

                        int totalSamples = chunkSize / bytesPerSample;

                        float[] samples = new float[totalSamples / channels];


                        for (int i = 0, j = 0; i < totalSamples; i++)

                        {

                            short s = br.ReadInt16();

                            if (channels == 1 || (i % channels == 0))

                                samples[j++] = s / 32768f;

                            if (channels == 2) br.ReadInt16(); // skip right

                        }

                        return samples;

                    }

                    else br.ReadBytes(chunkSize);

                }

            }

        }


        static void SaveWav(string path, float[] samples, int sampleRate, int channels)

        {

            int bitsPerSample = 16;

            int byteRate = sampleRate * channels * bitsPerSample / 8;

            int blockAlign = channels * bitsPerSample / 8;

            int dataSize = samples.Length * channels * 2;


            using (BinaryWriter bw = new BinaryWriter(File.Create(path)))

            {

                bw.Write(Encoding.ASCII.GetBytes("RIFF"));

                bw.Write(36 + dataSize);

                bw.Write(Encoding.ASCII.GetBytes("WAVE"));


                bw.Write(Encoding.ASCII.GetBytes("fmt "));

                bw.Write(16);

                bw.Write((short)1);

                bw.Write((short)channels);

                bw.Write(sampleRate);

                bw.Write(byteRate);

                bw.Write((short)blockAlign);

                bw.Write((short)bitsPerSample);


                bw.Write(Encoding.ASCII.GetBytes("data"));

                bw.Write(dataSize);


                foreach (float sample in samples)

                {

                    short s = (short)(sample * 32767);

                    for (int c = 0; c < channels; c++) bw.Write(s);

                }

            }

        }

    }


    public class SwaralipiConcatenator_DurationAware

    {

        public static void SwaralipiConcatenator___Main(string swaralipiFile)

        {

            string wavFolder = Path.GetDirectoryName(swaralipiFile);

            string outputStereo = swaralipiFile + "_(durationwise)_NOT_GOOD_output_8000_stereo.wav"; ;// "_output_44100_stereo.wav";

            string outputMono = swaralipiFile + "_(durationwise)_NOT_GOOD_output_8000_mono.wav";


            var lines = File.ReadAllLines(swaralipiFile)

                            .Where(l => !string.IsNullOrWhiteSpace(l)).ToList();


            var allSegments = new List<float>();


            foreach (var line in lines)

            {

                int durationMs = 220;

                var parts = line.Split(new[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries);

                if (parts.Length < 2) { durationMs = 220; continue; }


                string symbol = parts[0].Trim();

               // if (!int.TryParse(parts[1], out int durationMs)) continue;

                if (!int.TryParse(parts[1], out durationMs)) continue;


                symbol = symbol.Replace(".", "_DOT_").Replace("-", "dash").Replace("#", "hash");


                //.Replace("#", "hash").Replace(".", "_DOT_");

                string wavPath = Path.Combine(wavFolder, symbol + ".wav");



                float[] fullSamples = { };

                Array.Clear(fullSamples, 0, fullSamples.Length);


                fullSamples = ReadWavMonoAsFloats(wavPath, out int sampleRate);


                int requiredSamples = (int)((durationMs / 1000.0) * sampleRate);

                requiredSamples = Math.Min(requiredSamples, fullSamples.Length);


                float[] trimmed = new float[requiredSamples];

                Array.Copy(fullSamples, trimmed, requiredSamples);

                allSegments.AddRange(trimmed);

            }


            float[] final = allSegments.ToArray();


            SaveWav(outputStereo, final, 44100, 2);


            SaveWav(outputStereo, final, 8000, 2);

            SaveWav(outputMono, final, 8000, 1);


            Console.WriteLine("WAVs written with trimmed durations.");

            System.Windows.Forms.MessageBox.Show("Done writing WAVs with duration control:\n" + outputStereo + "\n" + outputMono);

        }


        static float[] ReadWavMonoAsFloats(string path, out int sampleRate)

        {

            using (BinaryReader br = new BinaryReader(File.OpenRead(path)))

            {

                string riff = new string(br.ReadChars(4));

                br.ReadInt32();

                string wave = new string(br.ReadChars(4));


                int channels = 1;

                sampleRate = 8000;// 44100;

                int bitsPerSample = 16;


                while (true)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSize = br.ReadInt32();


                    if (chunkID == "fmt ")

                    {

                        br.ReadInt16(); // format

                        channels = br.ReadInt16();

                        sampleRate = br.ReadInt32();

                        br.ReadInt32(); // byte rate

                        br.ReadInt16(); // block align

                        bitsPerSample = br.ReadInt16();

                        if (chunkSize > 16) br.ReadBytes(chunkSize - 16);

                        break;

                    }

                    else

                    {

                        br.ReadBytes(chunkSize);

                    }

                }


                while (true)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSize = br.ReadInt32();


                    if (chunkID == "data")

                    {

                        int bytesPerSample = bitsPerSample / 8;

                        int totalSamples = chunkSize / bytesPerSample;

                        float[] samples = { };


                        samples =

                            new float[totalSamples / channels];


                        Array.Clear(samples, 0, samples.Length);


                        for (int i = 0, j = 0; i < totalSamples; i++)

                        {

                            short sample = br.ReadInt16();

                            if (channels == 1 || (i % channels == 0))

                                samples[j++] = sample / 32768f;

                            if (channels == 2) br.ReadInt16(); // skip R

                        }

                        return samples;

                    }

                    else

                    {

                        br.ReadBytes(chunkSize);

                    }

                }

            }

        }


        static void SaveWav(string path, float[] samples, int sampleRate, int channels)

        {

            int bitsPerSample = 16;

            int byteRate = sampleRate * channels * bitsPerSample / 8;

            int blockAlign = channels * bitsPerSample / 8;

            int dataSize = samples.Length * channels * 2;


            using (BinaryWriter bw = new BinaryWriter(File.Create(path)))

            {

                bw.Write(Encoding.ASCII.GetBytes("RIFF"));

                bw.Write(36 + dataSize);

                bw.Write(Encoding.ASCII.GetBytes("WAVE"));


                bw.Write(Encoding.ASCII.GetBytes("fmt "));

                bw.Write(16);

                bw.Write((short)1);

                bw.Write((short)channels);

                bw.Write(sampleRate);

                bw.Write(byteRate);

                bw.Write((short)blockAlign);

                bw.Write((short)bitsPerSample);


                bw.Write(Encoding.ASCII.GetBytes("data"));

                bw.Write(dataSize);


                foreach (float sample in samples)

                {

                    short s = (short)(sample * 32767);

                    for (int c = 0; c < channels; c++)

                    {

                        bw.Write(s);

                    }//for (int c = 0; c < channels; c++)

                }//foreach (float sample in samples)

            }//using (BinaryWriter bw = new BinaryWriter(File.Create(path)))

        }

    }




    /// <summary>

    /// //////////////////////////////////////////////////////////////////////////////////////////////////

    /// </summary>



    public class SwaralipiConcatenator___all_same_durations

    {

        public static void SwaralipiConcatenator___Main(string swaralipifile)

        {

            string swaralipiFile = swaralipifile;// "swaralipi.txt"; // path to your text file

            string wavFolder 

                //= string folderPath =

                =Path.GetDirectoryName(swaralipifile); ;// "."; // directory containing all the 66 wavs

            string outputStereo = swaralipiFile + "_all_sames_durs_NOT_GOOD_output_8000_stereo.wav";// "_output_44100_stereo.wav";

            string outputMono = swaralipiFile + "_all_sames_durs_NOT_GOOD_output_8000_mono.wav";


            var symbols = File.ReadAllLines(swaralipiFile).Where(l => !string.IsNullOrWhiteSpace(l)).ToList();


            var allSamples = new List<float[]>();

            int maxSamples = 0;


            // Step 1: Load all WAVs and store sample data

            foreach (var symbol in symbols)

            {


                

                // var parts = line.Split(new[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries);

                string[] splitted_durations_notes= symbol.Split(new[] { ' ', '\t', ',' }, StringSplitOptions.RemoveEmptyEntries);


               // splitted_durations_notes

                string newsymbol = splitted_durations_notes[0].Replace(".", "_DOT_").Replace("-", "dash").Replace("#", "hash");



                //   string wavPath = Path.Combine(wavFolder, $"{symbol}.wav");


                string wavPath = "";

                wavPath= Path.Combine(wavFolder, $"{newsymbol}.wav");


                // List<float> samples = new List<float>();// null;


                float[] samples = { };// new List<float>();// null;

                //samples.Clear();

                Array.Clear(samples, 0, samples.Length);



                samples

                    =

                    ReadWavMonoAsFloats(wavPath, out int sourceRate);

                if (samples.Length > maxSamples) maxSamples = samples.Length;

                allSamples.Add(samples);

            }//foreach (var symbol in symbols)


            // Step 2: Resample all to maxSamples length

            var normalized = allSamples.Select(s => StretchToLength(s, maxSamples)).ToList();


            // Step 3: Concatenate all

            var finalFloat = normalized.SelectMany(s => s).ToList();


            // Step 4a: Save as 44100Hz stereo

            //  SaveWav(outputStereo+"_output_44100_stereo.wav", finalFloat.ToArray(), 44100, 2);

            SaveWav(outputStereo + "_output_8000_stereo.wav", finalFloat.ToArray(), 8000, 2);

            //SwaralipiConcatenator___all_same_durations


            // Step 4b: Save as 8000Hz mono

            SaveWav(outputMono+"_output_8000_mono.wav", finalFloat.ToArray(), 8000, 1);


            Console.WriteLine("Done writing output WAVs.");





























            System.Windows.Forms.MessageBox.Show("Done writing output WAVs." + outputStereo +"   " + outputMono);

        }//public static void SwaralipiConcatenator___Main(string swaralipifile)





        static float[] ReadWavMonoAsFloats(string path, out int sampleRate)

        {

            using (BinaryReader br = new BinaryReader(File.OpenRead(path)))

            {

                string riff = new string(br.ReadChars(4));

                br.ReadInt32(); // file size

                string wave = new string(br.ReadChars(4));


                int channels = 1;

                sampleRate = 8000;// 44100;

                int bitsPerSample = 16;













                // Read fmt chunk

                while (true)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSize = br.ReadInt32();


                    if (chunkID == "fmt ")

                    {

                        br.ReadInt16(); // audio format

                        channels = br.ReadInt16();

                        sampleRate = br.ReadInt32();

                        br.ReadInt32(); // byte rate

                        br.ReadInt16(); // block align

                        bitsPerSample = br.ReadInt16();

                        if (chunkSize > 16) br.ReadBytes(chunkSize - 16);

                        break;

                    }

                    else

                    {

                        br.ReadBytes(chunkSize); // skip unknown chunk

                    }

                }


                // Read data chunk

                while (true)

                {

                    string chunkID = new string(br.ReadChars(4));

                    int chunkSize = br.ReadInt32();


                    if (chunkID == "data")

                    {

                        int bytesPerSample = bitsPerSample / 8;

                        int totalSamples = chunkSize / bytesPerSample;

                        float[] samples = new float[totalSamples / channels];


                        for (int i = 0, j = 0; i < totalSamples; i++)

                        {

                            short sample = br.ReadInt16();

                            if (channels == 1 || (i % channels == 0))

                                samples[j++] = sample / 32768f;

                            if (channels == 2) br.ReadInt16(); // skip right channel

                        }

                        return samples;

                    }

                    else

                    {

                        br.ReadBytes(chunkSize); // skip unknown chunk

                    }

                }

            } // using BinaryReader

        }// static float[] ReadWavMonoAsFloats(string path, out int sampleRate)




        static float[] StretchToLength(float[] original, int targetLength)

        {

            float[] result = new float[targetLength];

            double step = (double)(original.Length - 1) / (targetLength - 1);


            for (int i = 0; i < targetLength; i++)

            {

                double index = i * step;

                int idx = (int)index;

                double frac = index - idx;


                result[i] = (idx + 1 < original.Length)

                    ? (float)((1 - frac) * original[idx] + frac * original[idx + 1])

                    : original[idx];

            }

            return result;

        }//static float[] StretchToLength(float[] original, int targetLength)


        static void SaveWav(string path, float[] samples, int sampleRate, int channels)

        {

            int bitsPerSample = 16;

            int byteRate = sampleRate * channels * bitsPerSample / 8;

            int blockAlign = channels * bitsPerSample / 8;

            int dataSize = samples.Length * channels * 2;


            using (BinaryWriter bw = new BinaryWriter(File.Create(path)))

            {

                // RIFF header

                bw.Write(Encoding.ASCII.GetBytes("RIFF"));

                bw.Write(36 + dataSize);

                bw.Write(Encoding.ASCII.GetBytes("WAVE"));


                // fmt chunk

                bw.Write(Encoding.ASCII.GetBytes("fmt "));

                bw.Write(16); // Subchunk1Size for PCM

                bw.Write((short)1); // Audio format = PCM

                bw.Write((short)channels);

                bw.Write(sampleRate);

                bw.Write(byteRate);

                bw.Write((short)blockAlign);

                bw.Write((short)bitsPerSample);


                // data chunk

                bw.Write(Encoding.ASCII.GetBytes("data"));

                bw.Write(dataSize);


                foreach (float sample in samples)

                {

                    short s = (short)(sample * 32767);

                    for (int c = 0; c < channels; c++)

                    {

                        bw.Write(s);

                    }

                }

            } // end using

        }//static void SaveWav(string path, float[] samples, int sampleRate, int channels)



    }//public class SwaralipiConcatenator















    public class SAANS_NO_3RD_PARTY_GPT_STYLES_WAV_FILES_READER_TO_GENERATE_8000_HZ_16_BIT_PCMS_GTAMPS

    {



        //////public static void Write_SPLITTED_WavFile(string path, List<float> normalizedSamples, int sampleRate)

        //////{

        //////    short bitsPerSample = 16;

        //////    short channels = 1;

        //////    int byteRate = sampleRate * channels * bitsPerSample / 8;

        //////    int dataSize = normalizedSamples.Count * 2;


        //////    using (var writer = new BinaryWriter(File.Create(path)))

        //////    {

        //////        writer.Write(Encoding.ASCII.GetBytes("RIFF"));

        //////        writer.Write(36 + dataSize);

        //////        writer.Write(Encoding.ASCII.GetBytes("WAVE"));


        //////        writer.Write(Encoding.ASCII.GetBytes("fmt "));

        //////        writer.Write(16);

        //////        writer.Write((short)1); // PCM

        //////        writer.Write((short)channels);

        //////        writer.Write(sampleRate);

        //////        writer.Write(byteRate);

        //////        writer.Write((short)(channels * bitsPerSample / 8));

        //////        writer.Write(bitsPerSample);


        //////        writer.Write(Encoding.ASCII.GetBytes("data"));

        //////        writer.Write(dataSize);

        //////        foreach (float sample in normalizedSamples)

        //////            writer.Write((short)(sample * 32767));

        //////    }//using (var writer = new BinaryWriter(File.Create(path)))

        //////}//public static void Write_SPLITTED_WavFile(string path, List<float> normalizedSamples, int sampleRate)










































        public static void SplitWavByAmplitudePercentilewith_dynamik_thresholds(string wavPath)

        {

            string fileNameOnly = Path.GetFileNameWithoutExtension(wavPath);

            string folder = Path.GetDirectoryName(wavPath);


            short channels = 1;

            int sampleRate = 8000;

            short bitsPerSample = 16;

            List<float> amplitudes = new List<float>();


            // ---- Read WAV and extract normalized amplitudes ----

            using (var reader = new BinaryReader(File.OpenRead(wavPath)))

            {

                if (new string(reader.ReadChars(4)) != "RIFF") throw new Exception("Invalid RIFF");

                reader.ReadInt32(); // size

                if (new string(reader.ReadChars(4)) != "WAVE") throw new Exception("Invalid WAVE");


                while (reader.BaseStream.Position < reader.BaseStream.Length)

                {

                    string chunkId = new string(reader.ReadChars(4));

                    int chunkSize = reader.ReadInt32();


                    if (chunkId == "fmt ")

                    {

                        reader.ReadInt16(); // audioFormat

                        channels = reader.ReadInt16();

                        sampleRate = reader.ReadInt32();

                        reader.ReadInt32(); // byteRate

                        reader.ReadInt16(); // blockAlign

                        bitsPerSample = reader.ReadInt16();

                        if (chunkSize > 16) reader.ReadBytes(chunkSize - 16);

                    }

                    else if (chunkId == "data")

                    {

                        int bytesPerSample = bitsPerSample / 8;

                        int totalSamples = chunkSize / bytesPerSample;


                        for (int i = 0; i < totalSamples; i++)

                        {

                            if (reader.BaseStream.Position + bytesPerSample > reader.BaseStream.Length)

                                break;


                            short sample = reader.ReadInt16();

                            float norm = sample / 32768f;

                            amplitudes.Add(norm);


                            if (channels == 2) reader.ReadInt16(); // skip right channel

                        }

                        break;

                    }

                    else reader.ReadBytes(chunkSize); // skip unknown

                }

            }


            // ---- Calculate 20th percentile of absolute amplitudes ----

            var absSorted = amplitudes.Select(Math.Abs).OrderBy(v => v).ToList();

            float percentile20 = absSorted[(int)(absSorted.Count * 0.2)];


            Console.WriteLine($"Using 20th Percentile Amplitude as Threshold: {percentile20:F6}");


            // ---- Detect rising/falling threshold crossings ----

            List<(int Start, int End)> regions = new List<(int, int)>();

            bool inRegion = false;

            int regionStart = 0;

            int minSegmentSamples = 800; // ~100 ms


            for (int i = 0; i < amplitudes.Count; i++)

            {

                float absAmp = Math.Abs(amplitudes[i]);


                if (!inRegion && absAmp >= percentile20)

                {

                    inRegion = true;

                    regionStart = i;

                }

                else if (inRegion && absAmp < percentile20)

                {

                    int regionEnd = i;

                    if (regionEnd - regionStart >= minSegmentSamples)

                        regions.Add((regionStart, regionEnd));

                    inRegion = false;

                }

            }


            // Handle edge case if region reaches file end

            if (inRegion && amplitudes.Count - regionStart >= minSegmentSamples)

                regions.Add((regionStart, amplitudes.Count - 1));


            // ---- Save split WAVs ----

            for (int i = 0; i < regions.Count; i++)

            {

                int start = regions[i].Start;

                int end = regions[i].End;

                var segment = amplitudes.GetRange(start, end - start);


                string outputFile = Path.Combine(folder,

                    $"{fileNameOnly}_piece_{i + 1}_samples_{segment.Count}_ms_{(int)(segment.Count / (float)sampleRate * 1000)}.wav");


                Write_SPLITTED_WavFile(outputFile, segment, sampleRate);

                Console.WriteLine($"Saved: {outputFile}");

            }


            if (regions.Count == 0)

                Console.WriteLine("No regions above the 20th percentile threshold were long enough to save.");

        }//public static void SplitWavByAmplitudePercentilewith_dynamik_thresholds(string wavPath)






        public static void SplitWavByRisingAbove20dBRegions(string wavPath)

        {

            string fileNameOnly = Path.GetFileNameWithoutExtension(wavPath);

            string folder = Path.GetDirectoryName(wavPath);


            short channels = 1;

            int sampleRate = 8000;

            short bitsPerSample = 16;

            List<float> amplitudes = new List<float>();


            // ---- Read WAV and extract normalized amplitudes ----

            using (var reader = new BinaryReader(File.OpenRead(wavPath)))

            {

                // Read RIFF/WAVE

                if (new string(reader.ReadChars(4)) != "RIFF") throw new Exception("Invalid RIFF");

                reader.ReadInt32(); // size

                if (new string(reader.ReadChars(4)) != "WAVE") throw new Exception("Invalid WAVE");


                while (reader.BaseStream.Position < reader.BaseStream.Length)

                {

                    string chunkId = new string(reader.ReadChars(4));

                    int chunkSize = reader.ReadInt32();


                    if (chunkId == "fmt ")

                    {

                        reader.ReadInt16(); // audioFormat

                        channels = reader.ReadInt16();

                        sampleRate = reader.ReadInt32();

                        reader.ReadInt32(); // byteRate

                        reader.ReadInt16(); // blockAlign

                        bitsPerSample = reader.ReadInt16();

                        if (chunkSize > 16) reader.ReadBytes(chunkSize - 16);

                    }

                    else if (chunkId == "data")

                    {

                        int bytesPerSample = bitsPerSample / 8;

                        int totalSamples = chunkSize / bytesPerSample;


                        for (int i = 0; i < totalSamples; i++)

                        {

                            if (reader.BaseStream.Position + bytesPerSample > reader.BaseStream.Length)

                                break;


                            short sample = reader.ReadInt16();

                            float norm = sample / 32768f;

                            amplitudes.Add(norm);


                            if (channels == 2) reader.ReadInt16(); // skip right

                        }

                        break;

                    }

                    else reader.ReadBytes(chunkSize);

                }

            }


            // ---- SPLITTING BASED ON AMPLITUDE THRESHOLD ----

            float threshold = 0.1f; // ~ -20 dB

            bool inRegion = false;

            int regionStart = 0;

            int minSegmentSamples = 800; // = 100ms worth (8000Hz)


            List<(int Start, int End)> regions = new List<(int, int)>();


            for (int i = 0; i < amplitudes.Count; i++)

            {

                float absAmp = Math.Abs(amplitudes[i]);


                if (!inRegion && absAmp >= threshold)

                {

                    inRegion = true;

                    regionStart = i;

                }

                else if (inRegion && absAmp < threshold)

                {

                    // End of region

                    int regionEnd = i;

                    if (regionEnd - regionStart >= minSegmentSamples)

                        regions.Add((regionStart, regionEnd));

                    inRegion = false;

                }

            }//for (int i = 0; i < amplitudes.Count; i++)


            // Edge case: still in region at end

            if (inRegion && amplitudes.Count - regionStart >= minSegmentSamples)

                regions.Add((regionStart, amplitudes.Count - 1));


            // ---- SAVE SPLIT WAVS ----

            for (int i = 0; i < regions.Count; i++)

            {

                int start = regions[i].Start;

                int end = regions[i].End;

                var segment = amplitudes.GetRange(start, end - start);


                string outputFile = Path.Combine(folder,

                    $"{fileNameOnly}_piece_{i + 1}_samples_{segment.Count}_ms_{(int)(segment.Count / (float)sampleRate * 1000)}.wav");


                Write_SPLITTED_WavFile(outputFile, segment, sampleRate);

                Console.WriteLine($"Saved: {outputFile}");

            }//for (int i = 0; i < regions.Count; i++)

        }//public static void SplitWavByRisingAbove20dBRegions(string wavPath)



        public static void DISCARDING___THIS_GENERATES_LARGE_NUMBER_OF_SPLITTED_FILES______SplitWavByLocalMinimals_Of_Amplitudes(string wavPath)

        {

            string fileNameOnly = Path.GetFileNameWithoutExtension(wavPath);

            string folder = Path.GetDirectoryName(wavPath);


            short channels = 1;

            int sampleRate = 8000;

            short bitsPerSample = 16;

            List<float> amplitudes = new List<float>();


            // ---- Read WAV and extract normalized amplitudes ----

            using (var reader = new BinaryReader(File.OpenRead(wavPath)))

            {

                // Validate RIFF and WAVE

                if (new string(reader.ReadChars(4)) != "RIFF") throw new Exception("Invalid RIFF");

                reader.ReadInt32(); // size

                if (new string(reader.ReadChars(4)) != "WAVE") throw new Exception("Invalid WAVE");


                while (reader.BaseStream.Position < reader.BaseStream.Length)

                {

                    string chunkId = new string(reader.ReadChars(4));

                    int chunkSize = reader.ReadInt32();


                    if (chunkId == "fmt ")

                    {

                        reader.ReadInt16(); // audioFormat

                        channels = reader.ReadInt16();

                        sampleRate = reader.ReadInt32();

                        reader.ReadInt32(); // byteRate

                        reader.ReadInt16(); // blockAlign

                        bitsPerSample = reader.ReadInt16();

                        if (chunkSize > 16) reader.ReadBytes(chunkSize - 16);

                    }

                    else if (chunkId == "data")

                    {

                        int bytesPerSample = bitsPerSample / 8;

                        int totalSamples = chunkSize / bytesPerSample;


                        for (int i = 0; i < totalSamples; i++)

                        {

                            if (reader.BaseStream.Position + bytesPerSample > reader.BaseStream.Length)

                                break;


                            short sample = reader.ReadInt16();

                            float norm = sample / 32768f;

                            amplitudes.Add(norm);


                            if (channels == 2) reader.ReadInt16(); // skip right

                        }

                        break;

                    }

                    else reader.ReadBytes(chunkSize); // skip unknown chunk

                }

            }


            // ---- Analyze: average and percentiles ----

            float avgAmp = amplitudes.Average(a => Math.Abs(a));

            float percentile20 = amplitudes.OrderBy(Math.Abs).ElementAt((int)(amplitudes.Count * 0.2f));

            float percentile50 = amplitudes.OrderBy(Math.Abs).ElementAt((int)(amplitudes.Count * 0.5f));


            Console.WriteLine($"Average Amplitude: {avgAmp:F4}");

            Console.WriteLine($"20th Percentile: {percentile20:F4}, 50th Percentile: {percentile50:F4}");


            // ---- Detect local minima ----

            List<int> minimaIndexes = new List<int>();

            for (int i = 1; i < amplitudes.Count - 1; i++)

            {

                if (Math.Abs(amplitudes[i]) < Math.Abs(amplitudes[i - 1]) &&

                    Math.Abs(amplitudes[i]) < Math.Abs(amplitudes[i + 1]))

                {

                    if (Math.Abs(amplitudes[i]) < percentile20)

                        minimaIndexes.Add(i);

                }

            }//for (int i = 1; i < amplitudes.Count - 1; i++)


            // ---- Extract segments between minima and save WAVs ----

            for (int i = 0; i < minimaIndexes.Count - 1; i++)

            {

                int start = minimaIndexes[i];

                int end = minimaIndexes[i + 1];

                var segment = amplitudes.GetRange(start, end - start);


                string outputFile = Path.Combine(folder,

                    $"{fileNameOnly}_piece_{i + 1}_samples_{segment.Count}_ms_{(int)(segment.Count / (float)sampleRate * 1000)}.wav");


                Write_SPLITTED_WavFile(outputFile, segment, sampleRate);

                Console.WriteLine($"Saved: {outputFile}");

            }//for (int i = 0; i < minimaIndexes.Count - 1; i++)










        }//public static void DISCARDING___THIS_GENERATES_LARGE_NUMBER_OF_SPLITTED_FILES______SplitWavByLocalMinimals_Of_Amplitudes(string wavPath)




        public static void Write_SPLITTED_WavFile(string path, List<float> normalizedSamples, int sampleRate)

        {

            short bitsPerSample = 16;

            short channels = 1;

            int byteRate = sampleRate * channels * bitsPerSample / 8;

            int dataSize = normalizedSamples.Count * 2;


            using (var writer = new BinaryWriter(File.Create(path)))

            {

                // RIFF header

                writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                writer.Write(36 + dataSize);

                writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                // fmt chunk

                writer.Write(Encoding.ASCII.GetBytes("fmt "));

                writer.Write(16);

                writer.Write((short)1); // PCM

                writer.Write((short)channels);

                writer.Write(sampleRate);

                writer.Write(byteRate);

                writer.Write((short)(channels * bitsPerSample / 8));

                writer.Write(bitsPerSample);


                // data chunk

                writer.Write(Encoding.ASCII.GetBytes("data"));

                writer.Write(dataSize);

                foreach (float sample in normalizedSamples)

                    writer.Write((short)(sample * 32767));

            }

        }//public static void Write_SPLITTED_WavFile(string path, List<float> normalizedSamples, int sampleRate)



        public static double PrintWavDurationAndSampleCount(string wavPath)

        {

            double durationMs = 0;

            string ___report = "";


            using (var reader = new BinaryReader(File.OpenRead(wavPath)))

            {

                // Skip RIFF header

                reader.ReadChars(4);

                reader.ReadInt32();

                reader.ReadChars(4);


                int sampleRate = 0;

                short channels = 1;

                short bitsPerSample = 16;

                int dataSize = 0;


                // Read chunks

                while (reader.BaseStream.Position < reader.BaseStream.Length)

                {

                    string chunkId = new string(reader.ReadChars(4));

                    int chunkSize = reader.ReadInt32();


                    if (chunkId == "fmt ")

                    {

                        short audioFormat = reader.ReadInt16();

                        channels = reader.ReadInt16();

                        sampleRate = reader.ReadInt32();

                        reader.ReadInt32(); // byteRate

                        reader.ReadInt16(); // blockAlign

                        bitsPerSample = reader.ReadInt16();


                        if (chunkSize > 16)

                            reader.ReadBytes(chunkSize - 16);

                    }

                    else if (chunkId == "data")

                    {

                        dataSize = chunkSize;

                        break;

                    }

                    else

                    {

                        reader.ReadBytes(chunkSize); // skip unknown chunk

                    }

                }//while (reader.BaseStream.Position < reader.BaseStream.Length)


                if (sampleRate == 0 || dataSize == 0)

                {

                    Console.WriteLine("Failed to read sample rate or data size.");

                    return 0;

                }//if (sampleRate == 0 || dataSize == 0)



































                int bytesPerSample = bitsPerSample / 8 * channels;

                int totalSamples = dataSize / bytesPerSample;

                 durationMs = (totalSamples / (double)sampleRate) * 1000;


                Console.WriteLine($"Sample Rate      : {sampleRate} Hz");

                Console.WriteLine($"Channels         : {channels}");

                Console.WriteLine($"Bits Per Sample  : {bitsPerSample}");

                Console.WriteLine($"Total Samples    : {totalSamples}");

                Console.WriteLine($"Total Duration   : {durationMs:F2} ms");


                












                 ___report= ___report + "\r\n"+ ($"Sample Rate      : {sampleRate} Hz");

                ___report = ___report + "\r\n" + ($"Channels         : {channels}");

                ___report = ___report + "\r\n" + ($"Bits Per Sample  : {bitsPerSample}");

                ___report = ___report + "\r\n" + ($"Total Samples    : {totalSamples}");

                ___report = ___report + "\r\n" + ($"Total Duration   : {durationMs:F2} ms");



                System.IO.File.WriteAllText(wavPath + "_reportfor_gtsmps.txt", ___report);

            }//using (var reader = new BinaryReader(File.OpenRead(wavPath)))

            return durationMs;

        }//public static void PrintWavDurationAndSampleCount(string wavPath)



        public static void ConvertWavToGTAMPS___with_corrections_GPT(string wavPath, string outputGtampsPath)

        {


            short channels = 1;

            int sampleRate = 8000;

            short bitsPerSample = 16;

            using (var reader = new BinaryReader(File.OpenRead(wavPath)))

            {

                // 1. Read RIFF header

                if (new string(reader.ReadChars(4)) != "RIFF")

                    throw new Exception("Not a valid RIFF file.");

                reader.ReadInt32(); // File size

                if (new string(reader.ReadChars(4)) != "WAVE")

                    throw new Exception("Not a valid WAVE file.");


                // 2. Find 'fmt ' subchunk

                 channels = 1;

                 sampleRate = 8000;

                 bitsPerSample = 16;

                while (true)

                {

                    string chunkId = new string(reader.ReadChars(4));

                    int chunkSize = reader.ReadInt32();


                    if (chunkId == "fmt ")

                    {

                        short audioFormat = reader.ReadInt16();

                        channels = reader.ReadInt16();

                        sampleRate = reader.ReadInt32();

                        reader.ReadInt32(); // byteRate

                        reader.ReadInt16(); // blockAlign

                        bitsPerSample = reader.ReadInt16();


                        if (chunkSize > 16)

                            reader.ReadBytes(chunkSize - 16); // skip extra fmt bytes

                        break;

                    }

                    else

                    {

                        reader.ReadBytes(chunkSize); // skip unknown chunk

                    }

                }


                // 3. Find 'data' subchunk

                while (true)

                {

                    string chunkId = new string(reader.ReadChars(4));

                    int chunkSize = reader.ReadInt32();

                    if (chunkId == "data")

                    {

                        int bytesPerSample = bitsPerSample / 8;

                        int totalSamples = chunkSize / bytesPerSample;

                        var amplitudes = new List<float>();


                        for (int i = 0; i < totalSamples; i++)

                        {

                            if (reader.BaseStream.Position + bytesPerSample > reader.BaseStream.Length)

                                break;


                            short sample = reader.ReadInt16();

                            float norm = sample / 32768f;

                            amplitudes.Add(norm);


                            if (channels == 2)

                                reader.ReadInt16(); // skip right channel

                        }


                        // 4. Resample if needed

                        if (sampleRate != 8000)

                        {

                            var resampled = new List<float>();

                            double factor = sampleRate / 8000.0;

                            for (int i = 0; i < amplitudes.Count / factor; i++)

                            {

                                double idx = i * factor;

                                int i0 = (int)idx;

                                double frac = idx - i0;

                                float val = (i0 + 1 < amplitudes.Count)

                                    ? (float)((1 - frac) * amplitudes[i0] + frac * amplitudes[i0 + 1])

                                    : amplitudes[i0];

                                resampled.Add(val);

                            }

                            amplitudes = resampled;

                        }
















                        // 5. Save GTAMPS

                          File.WriteAllLines(outputGtampsPath, amplitudes.Select(a => a.ToString("F8")));

                           Console.WriteLine($"Saved GTAMPS: {outputGtampsPath}");


                        System.Windows.Forms.MessageBox.Show($"Saved GTAMPS: {outputGtampsPath}   amplitudes =  {amplitudes.Count}");














                       //     string outputGtampsPath_generated = wavPath + "_actual_sampleRate=" + sampleRate + "_actual_bps=" + bitsPerSample + "_numSamples=" + numSamples + "_smpls=" + samples + "_8000Hz_16_bits_pcms_" + ".GTAMPS";

                       //samples

                       // Save as .GTAMPS

                       //   File.WriteAllLines(outputGtampsPath_generated, samples.Select(s => s.ToString("F8")));



                        return;

                    }

                    else

                    {

                        reader.ReadBytes(chunkSize); // skip unknown chunk

                    }

                }


                throw new Exception("Data chunk not found.");

            }

        }//public static void ConvertWavToGTAMPS___with_corrections_GPT(string wavPath, string outputGtampsPath)



        //////    public static void ConvertWavToGTAMPS___with_corrections_GPT(string wavPath, string outputGtampsPath)

        //////    {

        //////        using (var reader = new BinaryReader(File.OpenRead(wavPath)))

        //////        {

        //////            // 1. Read RIFF header

        //////            if (new string(reader.ReadChars(4)) != "RIFF")

        //////                throw new Exception("Not a valid RIFF file.");

        //////            reader.ReadInt32(); // File size

        //////            if (new string(reader.ReadChars(4)) != "WAVE")

        //////                throw new Exception("Not a valid WAVE file.");


        //////            // 2. Find 'fmt ' subchunk

        //////            short channels = 1;

        //////            int sampleRate = 8000;

        //////            short bitsPerSample = 16;

        //////            while (true)

        //////            {

        //////                string chunkId = new string(reader.ReadChars(4));

        //////                int chunkSize = reader.ReadInt32();


        //////                if (chunkId == "fmt ")

        //////                {

        //////                    short audioFormat = reader.ReadInt16();

        //////                    channels = reader.ReadInt16();

        //////                    sampleRate = reader.ReadInt32();

        //////                    reader.ReadInt32(); // byteRate

        //////                    reader.ReadInt16(); // blockAlign

        //////                    bitsPerSample = reader.ReadInt16();


        //////                    if (chunkSize > 16)

        //////                        reader.ReadBytes(chunkSize - 16); // skip extra fmt bytes

        //////                    break;

        //////                }

        //////                else

        //////                {

        //////                    reader.ReadBytes(chunkSize); // skip unknown chunk

        //////                }

        //////            }


        //////            // 3. Find 'data' subchunk

        //////            while (true)

        //////            {

        //////                string chunkId = new string(reader.ReadChars(4));

        //////                int chunkSize = reader.ReadInt32();

        //////                if (chunkId == "data")

        //////                {

        //////                    int bytesPerSample = bitsPerSample / 8;

        //////                    int totalSamples = chunkSize / bytesPerSample;

        //////                    var amplitudes = new List<float>();


        //////                    for (int i = 0; i < totalSamples; i++)

        //////                    {

        //////                        if (reader.BaseStream.Position + bytesPerSample > reader.BaseStream.Length)

        //////                        { break; }


        //////                        short sample = reader.ReadInt16();

        //////                        float norm = sample / 32768f;

        //////                        amplitudes.Add(norm);


        //////                        if (channels == 2)

        //////                        {

        //////                            reader.ReadInt16(); // skip right channel}

        //////                        }// for (int i = 0; i < totalSamples; i++)


        //////                        // 4. Resample if needed

        //////                        if (sampleRate != 8000)

        //////                    {

        //////                        var resampled = new List<float>();

        //////                        double factor = sampleRate / 8000.0;

        //////                        for (int rrr = 0; rrr < amplitudes.Count / factor; rrr++)

        //////                        {

        //////                            double idx = rrr * factor;

        //////                            int i0 = (int)idx;

        //////                            double frac = idx - i0;

        //////                            float val = (i0 + 1 < amplitudes.Count)

        //////                                ? (float)((1 - frac) * amplitudes[i0] + frac * amplitudes[i0 + 1])

        //////                                : amplitudes[i0];

        //////                            resampled.Add(val);

        //////                        }//for (int rrr = 0; rrr < amplitudes.Count / factor; rrr++)

        //////                        amplitudes = resampled;

        //////                    }//if (sampleRate != 8000)


        //////                    // 5. Save GTAMPS

        //////                    //   File.WriteAllLines(outputGtampsPath, amplitudes.Select(a => a.ToString("F8")));

        //////                    //   Console.WriteLine($"Saved GTAMPS: {outputGtampsPath}");
















        //////                    string outputGtampsPath_generated = wavPath + "_actual_sampleRate=" + sampleRate + "_actual_bps=" + bitsPerSample + "_numSamples=" + numSamples + "_smpls=" + samples + "_8000Hz_16_bits_pcms_" + ".GTAMPS";

        //////                    //samples

        //////                    // Save as .GTAMPS

        //////                    File.WriteAllLines(outputGtampsPath_generated, samples.Select(s => s.ToString("F8")));



        //////                    return;

        //////                }

        //////                else

        //////                {

        //////                    reader.ReadBytes(chunkSize); // skip unknown chunk

        //////                }

        //////            }


        //////            throw new Exception("Data chunk not found.");

        //////        }

        //////    }//public static void ConvertWavToGTAMPS___with_corrections_GPT(string wavPath, string outputGtampsPath)



        //////    public static void ConvertANY_KIND_OF_WavToGTAMPS(string wavPath, string outputGtampsPath)

        //////    {

        //////        using (var reader = new BinaryReader(File.OpenRead(wavPath)))

        //////        {

        //////            // Read RIFF header

        //////            string riff = new string(reader.ReadChars(4));

        //////            int fileSize = reader.ReadInt32();

        //////            string wave = new string(reader.ReadChars(4));


        //////            // Read format chunk

        //////            string fmt = new string(reader.ReadChars(4));

        //////            int fmtSize = reader.ReadInt32();

        //////            short audioFormat = reader.ReadInt16();

        //////            short channels = reader.ReadInt16();

        //////            int sampleRate = reader.ReadInt32();

        //////            int byteRate = reader.ReadInt32();

        //////            short blockAlign = reader.ReadInt16();

        //////            short bitsPerSample = reader.ReadInt16();


        //////            // Skip any extra bytes if fmt chunk > 16

        //////            if (fmtSize > 16)

        //////            { reader.ReadBytes(fmtSize - 16); }


        //////            // Seek to data chunk

        //////            while (new string(reader.ReadChars(4)) != "data")

        //////            {

        //////                reader.BaseStream.Position -= 3;

        //////            }//while (new string(reader.ReadChars(4)) != "data")








        //////            int dataSize = reader.ReadInt32();


        //////            int numSamples = dataSize / (bitsPerSample / 8);

        //////            var samples = new List<float>(numSamples);


        //////            for (int i = 0; i < numSamples; i++)

        //////            {

        //////                short sample16 = reader.ReadInt16();

        //////                float normalized = sample16 / 32768f;

        //////                samples.Add(normalized);

        //////                if (channels == 2) reader.ReadInt16(); // Skip second channel if stereo

        //////            }//for (int i = 0; i < numSamples; i++)


        //////            // Resample if needed (e.g., from 44100Hz to 8000Hz)

        //////            if (sampleRate != 8000)

        //////            {

        //////                var resampled = new List<float>();

        //////                double factor = sampleRate / 8000.0;



        //////                for (int i = 0; i < samples.Count / factor; i++)

        //////                {

        //////                    double index = i * factor;

        //////                    int idx = (int)index;

        //////                    double frac = index - idx;

        //////                    float sample = (idx + 1 < samples.Count)

        //////                        ? (float)((1 - frac) * samples[idx] + frac * samples[idx + 1])

        //////                        : samples[idx];

        //////                    resampled.Add(sample);

        //////                }//for (int i = 0; i < samples.Count / factor; i++)

        //////                samples = resampled;

        //////            }//if (sampleRate != 8000)


        //////           string  outputGtampsPath_generated= wavPath+ "_actual_sampleRate=" + sampleRate + "_actual_bps="+ bitsPerSample + "_numSamples=" + numSamples + "_smpls="+ samples+ "_8000Hz_16_bits_pcms_" + ".GTAMPS";

        //////            //samples

        //////            // Save as .GTAMPS

        //////            File.WriteAllLines(outputGtampsPath_generated, samples.Select(s => s.ToString("F8")));

        //////            // Console.WriteLine($"Saved GTAMPS to: {outputGtampsPath}");


        //////            System.Windows.Forms.MessageBox.Show($"Saved GTAMPS to: {outputGtampsPath}");

        //////        }//using (var reader = new BinaryReader(File.OpenRead(wavPath)))














        //////    }//public static void ConvertWavToGTAMPS(string wavPath, string outputGtampsPath)


    }// public class SAANS_NO_3RD_PARTY_GPT_STYLES_WAV_FILES_READER_TO_GENERATE_8000_HZ_16_BIT_PCMS_GTAMPS




    // this changes speed when frequencies changes

    public class WavGenerator___44_SHRUTIS_BACKWARD_TO_FORWARDS_Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis

    {

        const int SampleRate = 8000;

        const int BitsPerSample = 16;

        const int Channels = 1;

        const double Pi = Math.PI;



 


        public static void SAANS___44_SAMPLES_WavGenerator___Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis___Main(string gtamps_filesnames)

        {

            string inputPath = gtamps_filesnames;// "your_file_path_here.txt";



            // Read float samples

            var samples = File.ReadLines(inputPath)

                              .Where(line => double.TryParse(line, out _))

                              .Select(double.Parse)

                              .ToList();


            var allShifted = new List<short>();


            for (int r = 1; r <= 22; r++)

            {

                double shiftFactor = Math.Pow(2, r / 22.0);

                var shifted = ResampleWithFrequencyShift(samples, shiftFactor);

                allShifted.AddRange(shifted);

            }//for (int r = 1; r <= 22; r++)




            for (int r = -22; r <= 0; r++)

            {

                double shiftFactor = Math.Pow(2, r / 22.0);

                var shifted = ResampleWithFrequencyShift(samples, shiftFactor);

                allShifted.AddRange(shifted);

            }//for (int r = -22; r <= 0; r++)





            string outputPath = inputPath + "___44_SCALES_8000hZ_16_BITS_PCMS_" + allShifted.Count.ToString() + "_output.wav";


            WriteWavFile(outputPath, allShifted);

            Console.WriteLine("WAV file written to: " + outputPath);

        }//public static void SAANS___44_SAMPLES_WavGenerator___Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis___Main(STRING gtamps_filesnames)


        public static List<short> ResampleWithFrequencyShift(List<double> samples, double shiftFactor)

        {

            int newLength = (int)(samples.Count / shiftFactor);

            var shifted = new List<short>(newLength);


            for (int i = 0; i < newLength; i++)

            {

                double srcIndex = i * shiftFactor;

                int idx = (int)srcIndex;

                double frac = srcIndex - idx;


                double value = 0;

                if (idx + 1 < samples.Count)

                    value = (1 - frac) * samples[idx] + frac * samples[idx + 1];

                else if (idx < samples.Count)

                    value = samples[idx];


                short pcmVal = (short)(value * short.MaxValue);

                shifted.Add(pcmVal);

            }//for (int i = 0; i < newLength; i++)


            return shifted;

        }//public static List<short> ResampleWithFrequencyShift(List<double> samples, double shiftFactor)


        public static void WriteWavFile(string filePath, List<short> samples)

        {

            using (var stream = new FileStream(filePath, FileMode.Create))

            using (var writer = new BinaryWriter(stream))

            {

                int byteRate = SampleRate * Channels * BitsPerSample / 8;

                int dataSize = samples.Count * BitsPerSample / 8;


                // RIFF header

                writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                writer.Write(36 + dataSize);

                writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                // fmt subchunk

                writer.Write(Encoding.ASCII.GetBytes("fmt "));

                writer.Write(16); // PCM

                writer.Write((short)1); // AudioFormat = PCM

                writer.Write((short)Channels);

                writer.Write(SampleRate);

                writer.Write(byteRate);

                writer.Write((short)(Channels * BitsPerSample / 8));

                writer.Write((short)BitsPerSample);


                // data subchunk

                writer.Write(Encoding.ASCII.GetBytes("data"));

                writer.Write(dataSize);

                foreach (short s in samples)

                { writer.Write(s); }

            }//using (var writer = new BinaryWriter(stream))

        }//public static void WriteWavFile(string filePath, List<short> samples)

    }// public class WavGenerator___44_SHRUTIS_BACKWARD_TO_FORWARDS_Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis




    // this dont change speed when frequencies changes

    public class WavGenerator___44_KEEPING_SHRUTIS_FIXED_DURATION

    {

        const int SampleRate = 8000;

        const int BitsPerSample = 16;

        const int Channels = 1;


        public static void function_to___WavGenerator___44_KEEPING_SHRUTIS_FIXED_DURATION___Main(string gtampsFilePath)

        {

            var samples = File.ReadLines(gtampsFilePath)

                              .Where(line => double.TryParse(line, out _))

                              .Select(double.Parse)

                              .ToList();


            int originalLength = samples.Count;

            var allShifted = new List<short>();
















            // Positive shrutis

            for (int r = 1; r <= 22; r++)

            {

                double shiftFactor = Math.Pow(2, r / 22.0);

                var shifted = PitchShiftPreserveDuration(samples, shiftFactor, originalLength);

                allShifted.AddRange(shifted);

            }//for (int r = 1; r <= 22; r++)


            // Negative shrutis

            for (int r = -22; r <= 0; r++)

            {

                double shiftFactor = Math.Pow(2, r / 22.0);

                var shifted = PitchShiftPreserveDuration(samples, shiftFactor, originalLength);

                allShifted.AddRange(shifted);

            }//for (int r = -22; r <= 0; r++)


            string outputPath = gtampsFilePath + "(speed_intact)___44_FIXEDDUR_SCALES_8000Hz_16bit_" + allShifted.Count + "_output.wav";

            // WriteWavFile(outputPath, allShifted);

            WriteWavFile___another_keeping_speed_same(outputPath, allShifted);

            Console.WriteLine("WAV file written to: " + outputPath);

            System.Windows.Forms.MessageBox.Show("(Speeds intact)WAV file written to: " + outputPath);

        }//public static void function_to___WavGenerator___44_KEEPING_SHRUTIS_FIXED_DURATION___Main(string gtampsFilePath)


        // Shifts pitch and then stretches result back to original duration

        //////public static List<short> PitchShiftPreserveDuration(List<double> samples, double shiftFactor, int targetLength)

        //////{

        //////    // Step 1: Resample with frequency shift (changes duration)

        //////    int shiftedLength = (int)(samples.Count / shiftFactor);

        //////    var shifted = new List<double>(shiftedLength);


        //////    for (int i = 0; i < shiftedLength; i++)

        //////    {

        //////        double srcIndex = i * shiftFactor;

        //////        int idx = (int)srcIndex;

        //////        double frac = srcIndex - idx;


        //////        double value = 0;

        //////        if (idx + 1 < samples.Count)

        //////        { value = (1 - frac) * samples[idx] + frac * samples[idx + 1]; }

        //////        else if (idx < samples.Count)

        //////        { value = samples[idx]; }


        //////        shifted.Add(value);

        //////    }//for (int i = 0; i < shiftedLength; i++)


        //////    // Step 2: Time-stretch to match original length

        //////    var stretched = new List<short>(targetLength);

        //////    double step = (double)(shifted.Count - 1) / (targetLength - 1);

        //////    for (int i = 0; i < targetLength; i++)

        //////    {

        //////        double index = i * step;

        //////        int idx = (int)index;

        //////        double frac = index - idx;


        //////        double val = 0;

        //////        if (idx + 1 < shifted.Count)

        //////        { val = (1 - frac) * shifted[idx] + frac * shifted[idx + 1]; }

        //////        else if (idx < shifted.Count)

        //////        { val = shifted[idx]; }


        //////        short pcmVal = (short)(val * short.MaxValue);

        //////        stretched.Add(pcmVal);

        //////    }//for (int i = 0; i < targetLength; i++)


        //////    return stretched;

        //////}//public static List<short> PitchShiftPreserveDuration(List<double> samples, double shiftFactor, int targetLength)









        public static List<short> PitchShiftPreserveDuration(List<double> samples, double shiftFactor, int targetLength)

        {

            var output = new List<short>(targetLength);

            double position = 0.0;

            double positionStep = shiftFactor;


            for (int i = 0; i < targetLength; i++)

            {

                int idx = (int)position;

                double frac = position - idx;


                double value = 0;

                if (idx + 1 < samples.Count)

                    value = (1 - frac) * samples[idx] + frac * samples[idx + 1];

                else if (idx < samples.Count)

                    value = samples[idx];


                short pcmVal = (short)(value * short.MaxValue);

                output.Add(pcmVal);


                position += positionStep;

                if (position >= samples.Count - 1)

                    position = 0; // loop back if needed to keep filling output

            }//for (int i = 0; i < targetLength; i++)


            return output;

        }// public static List<short> PitchShiftPreserveDuration(List<double> samples, double shiftFactor, int targetLength)









        public static void WriteWavFile___another_keeping_speed_same(string filePath, List<short> samples)

        {

            using (var stream = new FileStream(filePath, FileMode.Create))

            {


                using (var writer = new BinaryWriter(stream))

                {

                    int byteRate = SampleRate * Channels * BitsPerSample / 8;

                    int dataSize = samples.Count * BitsPerSample / 8;


                    // RIFF header

                    writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                    writer.Write(36 + dataSize);

                    writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                    // fmt chunk

                    writer.Write(Encoding.ASCII.GetBytes("fmt "));

                    writer.Write(16);

                    writer.Write((short)1); // PCM

                    writer.Write((short)Channels);

                    writer.Write(SampleRate);

                    writer.Write(byteRate);

                    writer.Write((short)(Channels * BitsPerSample / 8));

                    writer.Write((short)BitsPerSample);


                    // data chunk

                    writer.Write(Encoding.ASCII.GetBytes("data"));

                    writer.Write(dataSize);

                    foreach (short s in samples)

                    { writer.Write(s); }

                }//using (var writer = new BinaryWriter(stream))

            }//using (var stream = new FileStream(filePath, FileMode.Create))

        }//public static void WriteWavFile___another_keeping_speed_same(string filePath, List<short> samples)

    }//public class WavGenerator___44_KEEPING_SHRUTIS_FIXED_DURATION





  













  public class WavGenerator___44_KEEPING_DURATION_VARIABLE_SAMPLE_RATE

    {

        const int BaseSampleRate = 8000;

        const int BitsPerSample = 16;

        const int Channels = 1;


        public static void function_to___WavGenerator___44_KEEPING_DURATION_VARIABLE_SAMPLE_RATE___Main(string gtampsFilePath)

        {

            var samples = File.ReadLines(gtampsFilePath)

                              .Where(line => double.TryParse(line, out _))

                              .Select(double.Parse)

                              .ToList();


            int totalSamples = samples.Count;


            for (int r = 1; r <= 22; r++)

            {

                double shiftFactor = Math.Pow(2, r / 22.0);

                int newSampleRate = (int)(BaseSampleRate * shiftFactor);

                string outputPath = gtampsFilePath + $"___shruti_up_{r}_samplerate_{newSampleRate}.wav";

                WriteWavFile_WithCustomSampleRate(outputPath, samples, newSampleRate);

            }//for (int r = 1; r <= 22; r++)


            for (int r = -22; r <= 0; r++)

            {

                double shiftFactor = Math.Pow(2, r / 22.0);

                int newSampleRate = (int)(BaseSampleRate * shiftFactor);

                string outputPath = gtampsFilePath + $"___shruti_down_{Math.Abs(r)}_samplerate_{newSampleRate}.wav";

                WriteWavFile_WithCustomSampleRate(outputPath, samples, newSampleRate);

            }//for (int r = -22; r <= 0; r++)


            Console.WriteLine("44 pitch-shifted files written with variable sample rates (durations preserved).");

            System.Windows.Forms.MessageBox.Show("WAVs written: duration preserved, pitch changed, sample rates varied.");

        }//public static void function_to___WavGenerator___44_KEEPING_DURATION_VARIABLE_SAMPLE_RATE___Main(string gtampsFilePath)


        public static void WriteWavFile_WithCustomSampleRate(string filePath, List<double> samples, int sampleRate)

        {

            using (var stream = new FileStream(filePath, FileMode.Create))

            {

                using (var writer = new BinaryWriter(stream))

                {

                    int byteRate = sampleRate * Channels * BitsPerSample / 8;

                    int dataSize = samples.Count * BitsPerSample / 8;


                    // RIFF header

                    writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                    writer.Write(36 + dataSize);

                    writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                    // fmt chunk

                    writer.Write(Encoding.ASCII.GetBytes("fmt "));

                    writer.Write(16);

                    writer.Write((short)1); // PCM

                    writer.Write((short)Channels);

                    writer.Write(sampleRate); // <-- variable sample rate here

                    writer.Write(byteRate);

                    writer.Write((short)(Channels * BitsPerSample / 8));

                    writer.Write((short)BitsPerSample);


                    // data chunk

                    writer.Write(Encoding.ASCII.GetBytes("data"));

                    writer.Write(dataSize);

                    foreach (double sample in samples)

                    {

                        short s = (short)(sample * short.MaxValue);

                        writer.Write(s);

                    }

                }//using writer

            }//using stream

        }//public static void WriteWavFile_WithCustomSampleRate(...)

    }//class WavGenerator___44_KEEPING_DURATION_VARIABLE_SAMPLE_RATE


    /// <summary>

    /// /////////////////////////////////////////////////////////////////////////////////////

    /// </summary>























    public class WavGenerator___12x3_ChromaticShrutis_From_SAA_GTAMPS

    {

        const int BaseSampleRate = 8000;

        const int BitsPerSample = 16;

        const int Channels = 1;


        public static StringBuilder ___combined_all_gtamps = new StringBuilder();


        public static void function_to___Generate_All_12x3_SemitoneNotes_From_SAA_GTAMPS(string gtampsFilePath)

        {

            ___combined_all_gtamps.Clear();


            var samples = File.ReadLines(gtampsFilePath)

                              .Where(line => double.TryParse(line, out _))

                              .Select(double.Parse)

                              .ToList();


            // These 36 labels are expected exactly from your shruti table

            string[] noteLabels = new string[]

            {

            ".S", ".R", ".R#", ".G", ".G#", ".M", ".M#", ".P", ".D", ".D#", ".N", ".N#",

            "S", "R", "R#", "G", "G#", "M", "M#", "P", "D", "D#", "N", "N#",

            "S.", "R.", "R#.", "G.", "G#.", "M.", "M#.", "P.", "D.", "D#.", "N.", "N#.","dash"

            };


            for (int i = 0; i < noteLabels.Length; i++)

            {

                double semitoneShift = i - 12; // Make "S" (index 12) the base reference (0)

                double shiftFactor = Math.Pow(2.0, semitoneShift / 12.0);

                int newSampleRate = (int)(BaseSampleRate * shiftFactor);


                string fileName = noteLabels[i].Replace("#", "hash").Replace(".", "_DOT_");

                string outputPath = Path.Combine(Path.GetDirectoryName(gtampsFilePath), fileName + ".wav");


                WriteWavFile_WithCustomSampleRate(outputPath, samples, newSampleRate, fileName);

            }//for (int i = 0; i < noteLabels.Length; i++)


            // Save the entire concatenated GTAMPS (optional master file)

            File.WriteAllText(gtampsFilePath + "_36_notes_combined.gtamps", ___combined_all_gtamps.ToString());


            Console.WriteLine("36 chromatic notes across 3 octaves generated.");

            System.Windows.Forms.MessageBox.Show("36 chromatic WAVs written from Sa sample.");

        }//public static void function_to___Generate_All_12x3_SemitoneNotes_From_SAA_GTAMPS(string gtampsFilePath)


        public static void WriteWavFile_WithCustomSampleRate(string filePath, List<double> samples, int sampleRate, string noteLabel)

        {

            using (var stream = new FileStream(filePath, FileMode.Create))

            using (var writer = new BinaryWriter(stream))

            {

                int byteRate = sampleRate * Channels * BitsPerSample / 8;

                int dataSize = samples.Count * BitsPerSample / 8;


                // RIFF header

                writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                writer.Write(36 + dataSize);

                writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                // fmt chunk

                writer.Write(Encoding.ASCII.GetBytes("fmt "));

                writer.Write(16);

                writer.Write((short)1); // PCM

                writer.Write((short)Channels);

                writer.Write(sampleRate);

                writer.Write(byteRate);

                writer.Write((short)(Channels * BitsPerSample / 8));

                writer.Write((short)BitsPerSample);


                // data chunk

                writer.Write(Encoding.ASCII.GetBytes("data"));

                writer.Write(dataSize);


                var sb = new StringBuilder();


                foreach (double sample in samples)

                {

                    short s = (short)(sample * short.MaxValue);



                    if(filePath.Contains("dash"))

                    {



                        writer.Write((short)0.0000001);


                        string textVal = "0.0000001";// s.ToString("F8");



                        sb.AppendLine(textVal);

                        ___combined_all_gtamps.AppendLine(textVal);


                    }

                    else

                    {


                        writer.Write(s);


                        string textVal = s.ToString("F8");



                        sb.AppendLine(textVal);

                        ___combined_all_gtamps.AppendLine(textVal);


                    }//end of else of if(filePath.Contains("dash"))


                }//foreach (double sample in samples)


                File.WriteAllText(filePath + ".gtamps", sb.ToString());

            }//using (var writer = new BinaryWriter(stream))








        } //public static void WriteWavFile_WithCustomSampleRate(string filePath, List<double> samples, int sampleRate, string noteLabel)

    }//public class WavGenerator___12x3_ChromaticShrutis_From_SAA_GTAMPS




    /// <summary>

    /// //////////////////////////////////////////////////////////////////////////////

    /// </summary>


    public class WavGenerator___ShrutiLibrary_From_SAA_Sample

    {

        const int BaseSampleRate = 8000;

        const int BitsPerSample = 16;

        const int Channels = 1;


       public static StringBuilder ___public_static_combined_for_88_shrutis_in_one_gtamps_stringBuilder = new StringBuilder();

      


        public static void function_to___Generate_All_Shrutis_From_SAA_GTAMPS(string gtampsFilePath)

        {



            ___public_static_combined_for_88_shrutis_in_one_gtamps_stringBuilder = new StringBuilder();

            ___public_static_combined_for_88_shrutis_in_one_gtamps_stringBuilder.Clear();

            var samples = File.ReadLines(gtampsFilePath)

                              .Where(line => double.TryParse(line, out _))

                              .Select(double.Parse)

                              .ToList();


            // All shruti names mapped to their shift positions (-22 to +22)

            string[] shrutiNames = new string[]

            {

            "L_Re1", "L_Re2", "L_Ma2S", "L_Pa2", "M_Sa", "M_Re1", "M_Re2", "M_Re", "M_Ga1", "M_Ga2", "M_Ga",

            "M_Ma", "M_Ma1", "M_Ma2", "M_Pa", "M_Dha1", "M_Dha2", "L_Re", "L_Ga1", "L_Ga2", "L_Ga", "L_Ma",

            "L_Ma1", "L_Ma2", "L_Pa", "L_Dha1", "L_Dha2", "L_Dha", "L_Ni1", "L_Ni2", "L_Ni2", "L_Re2S",

            "L_Ga2S", "M_Dha", "M_Ni1", "M_Ni2", "M_Ni", "M_Sa2", "M_Re2S", "M_Ga2S", "M_Ma2S", "M_Pa2",

            "U_Sa", "U_Re1", "U_Re2", "U_Re", "L_Ma2S", "L_Pa2", "M_Sa", "M_Re1", "M_Re2", "M_Re", "M_Ga1",

            "M_Ga2", "M_Ga", "M_Ma", "M_Ma1", "M_Ma2", "M_Pa", "M_Dha1", "M_Dha2", "L_Re", "L_Ga1", "L_Ga2",

            "L_Ga", "L_Ma", "L_Ma1", "L_Ma2", "L_Pa", "L_Dha1", "U_Ga1", "U_Ga2", "U_Ga", "U_Ma", "U_Ma1",

            "U_Ma2", "U_Pa", "U_Dha1", "U_Dha2", "U_Dha", "U_Ni1", "U_Ni2", "U_Ni", "U_Sa2", "U_Re2S",

            "U_Ga2S", "U_Ma2S", "U_Pa2","dash"

            };


            int totalShrutis = shrutiNames.Length;






            for (int r = 0; r < totalShrutis; r++)

            {

                int shrutiIndex = r - 22;

                double shiftFactor = Math.Pow(2, shrutiIndex / 22.0);

                int newSampleRate = (int)(BaseSampleRate * shiftFactor);


                string fileName = shrutiNames[r];

                //////string outputPath = Path.Combine(Path.GetDirectoryName(gtampsFilePath),

                //////                                 fileName + "_shruti.wav");

                ///


                string outputPath = Path.Combine(Path.GetDirectoryName(gtampsFilePath),

                                                 fileName + ".wav");


                WriteWavFile_WithCustomSampleRate(outputPath, samples, newSampleRate);

            }//for (int r = 0; r < totalShrutis; r++)


            System.IO.File.WriteAllText

                (

                gtampsFilePath+"_combined_88_shrutis.GTAMPS"

                ,

                ___public_static_combined_for_88_shrutis_in_one_gtamps_stringBuilder.ToString()

                );


            



            Console.WriteLine($"{totalShrutis} shruti files written using sample rate modulation.");

            System.Windows.Forms.MessageBox.Show($"{totalShrutis} shruti WAVs written from SAA sample.");

        }//public static void function_to___Generate_All_Shrutis_From_SAA_GTAMPS


        public static void WriteWavFile_WithCustomSampleRate(string filePath, List<double> samples, int sampleRate)

        {




            using (var stream = new FileStream(filePath, FileMode.Create))

            {


            

            using (var writer = new BinaryWriter(stream))

            {

                  

                int byteRate = sampleRate * Channels * BitsPerSample / 8;

                int dataSize = samples.Count * BitsPerSample / 8;


                // RIFF header

                writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                writer.Write(36 + dataSize);

                writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                // fmt chunk

                writer.Write(Encoding.ASCII.GetBytes("fmt "));

                writer.Write(16);

                writer.Write((short)1); // PCM

                writer.Write((short)Channels);

                writer.Write(sampleRate);

                writer.Write(byteRate);

                writer.Write((short)(Channels * BitsPerSample / 8));

                writer.Write((short)BitsPerSample);


                // data chunk

                writer.Write(Encoding.ASCII.GetBytes("data"));

                writer.Write(dataSize);









                    StringBuilder ___temp_stringbuilder_for_current_shrutis_GTAMPS = new StringBuilder();

                    ___temp_stringbuilder_for_current_shrutis_GTAMPS.Clear();














                    foreach (double sample in samples)

                {

                    short s = (short)(sample * short.MaxValue);



                        if(filePath.Contains("dash"))

                            {

                            writer.Write((short)0.000001);


                            ___public_static_combined_for_88_shrutis_in_one_gtamps_stringBuilder

                                .AppendLine("0.000001");


                            ___temp_stringbuilder_for_current_shrutis_GTAMPS

                                  .AppendLine("0.000001");

                        }

                        else

                        {


                            writer.Write(s);


                            ___public_static_combined_for_88_shrutis_in_one_gtamps_stringBuilder

                                .AppendLine(s.ToString("F8"));


                            ___temp_stringbuilder_for_current_shrutis_GTAMPS

                                 .AppendLine(s.ToString("F8"));

                        }//endof else of  if(filePath.Contains("dash"))

                        

                    }//foreach (double sample in samples)



                ///////////////////////////////////////////////////////////////////////////////////////////

                    System.IO.File.WriteAllText

                            (

                        filePath + "_bytrts_" + byteRate+"_sps_"+ sampleRate+ "_dtsizes_"+ dataSize + "_samples_" + samples.Count + "_" + ".gtamps"

                          ,

                        ___temp_stringbuilder_for_current_shrutis_GTAMPS.ToString()

                        );


                }// using (var writer = new BinaryWriter(stream))

            }//using (var stream = new FileStream(filePath, FileMode.Create))

        }//public static void WriteWavFile_WithCustomSampleRate

    }//public class WavGenerator___ShrutiLibrary_From_SAA_Sample




    //////public class WavGenerator___MultiPitch_SingleFile_FixedDurations

    //////{

    //////    const int BaseSampleRate = 44100;// 8000; // can be increased for higher resolution

    //////    const int BitsPerSample = 16;

    //////    const int Channels = 1;


    //////    public static void function_to___ApplyPerRegionPitchShift_AND_SaveUnifiedWav(string gtampsFilePath, int numRegions)

    //////    {

    //////        var originalSamples = File.ReadLines(gtampsFilePath)

    //////                                  .Where(line => double.TryParse(line, out _))

    //////                                  .Select(double.Parse)

    //////                                  .ToList();


    //////        // Apply pitch shifts to each region

    //////        List<short> finalPcm = ApplyPerRegionPitchShift(originalSamples, numRegions);


    //////        // Save to single WAV

    //////        string outputPath = gtampsFilePath + $"CONCATENATED____{numRegions}_Regions_MultiPitch_FixedDuration_output.wav";

    //////        WriteWavFile___SingleFile_ConstantSampleRate(outputPath, finalPcm, BaseSampleRate);


    //////        Console.WriteLine("Unified WAV written with pitch-shifted segments (duration preserved).");

    //////        System.Windows.Forms.MessageBox.Show("Unified WAV written with pitch-shifted segments (duration preserved): " + outputPath);

    //////    }//public static void function_to___ApplyPerRegionPitchShift_AND_SaveUnifiedWav(...)


    //////    public static List<short> ApplyPerRegionPitchShift(List<double> original, int numRegions)

    //////    {

    //////        //////int totalSamples = original.Count;

    //////        //////int segmentLength = totalSamples / numRegions;

    //////        //////List<short> output = new List<short>();


    //////        int totalSamples = original.Count * numRegions;//SAAN CHANGES THIS SINCE I THINK IF I NEED 44 COPIES THEN THERE NEEDS 44 TIMES ORIGINAL DURATION IN CONCATENATED FILES PLAY TIMES

    //////        int segmentLength = totalSamples / numRegions;

    //////        List<short> output = new List<short>();// OBVIOUSLY IF I AM GENERATING N NUMBERS OF PITCH CHANGED COPIES THEN ATLEAST N NUMBER OF TIMES ORIGINAL SAMPLES COUNT TO REPEAT


    //////        Random rnd = new Random();//??? WHY IS THIS??????????


    //////        for (int region = 0; region < numRegions; region++)

    //////        {

    //////            var segment = original.Skip(region * segmentLength).Take(segmentLength).ToList();


    //////            // Choose a shift factor (shruti-style): use 2^(r/22.0), r from -22 to +22

    //////            int shrutiStep = -22 + (44 * region / numRegions); // evenly spaced across shruti scale

    //////            // ALL OF THESE    COPIED REGIONS NEED SAME DURATION OF PLAY TIME AS ACTUAL totalSamples PLAY TIME FREQUENCIES ARE TO CHANGE


    //////            double shiftFactor = Math.Pow(2, shrutiStep / 22.0);


    //////            var regionPcm = PitchShift_PreserveDuration(segment, shiftFactor, segmentLength);

    //////            output.AddRange(regionPcm);

    //////        }


    //////        return output;

    //////    }//public static List<short> ApplyPerRegionPitchShift(List<double> original, int numRegions)


    //////    public static List<short> PitchShift_PreserveDuration(List<double> input, double shiftFactor, int outputLength)

    //////    {

    //////        var result = new List<short>(outputLength);

    //////        double pos = 0.0;

    //////        double posStep = shiftFactor;


    //////        for (int i = 0; i < outputLength; i++)

    //////        {

    //////            int idx = (int)pos;

    //////            double frac = pos - idx;


    //////            double value = 0;

    //////            if (idx + 1 < input.Count)

    //////                value = (1 - frac) * input[idx] + frac * input[idx + 1];

    //////            else if (idx < input.Count)

    //////                value = input[idx];


    //////            short pcmVal = (short)(value * short.MaxValue);

    //////            result.Add(pcmVal);


    //////            pos += posStep;

    //////            if (pos >= input.Count - 1)

    //////                pos = 0; // loop or clamp, depending on preference

    //////        }


    //////        return result;

    //////    }//public static List<short> PitchShift_PreserveDuration(...)


    //////    public static void WriteWavFile___SingleFile_ConstantSampleRate(string filePath, List<short> samples, int sampleRate)

    //////    {

    //////        using (var stream = new FileStream(filePath, FileMode.Create))

    //////        using (var writer = new BinaryWriter(stream))

    //////        {

    //////            int byteRate = sampleRate * Channels * BitsPerSample / 8;

    //////            int dataSize = samples.Count * BitsPerSample / 8;


    //////            // RIFF header

    //////            writer.Write(Encoding.ASCII.GetBytes("RIFF"));

    //////            writer.Write(36 + dataSize);

    //////            writer.Write(Encoding.ASCII.GetBytes("WAVE"));


    //////            // fmt chunk

    //////            writer.Write(Encoding.ASCII.GetBytes("fmt "));

    //////            writer.Write(16);

    //////            writer.Write((short)1); // PCM

    //////            writer.Write((short)Channels);

    //////            writer.Write(sampleRate);

    //////            writer.Write(byteRate);

    //////            writer.Write((short)(Channels * BitsPerSample / 8));

    //////            writer.Write((short)BitsPerSample);


    //////            // data chunk

    //////            writer.Write(Encoding.ASCII.GetBytes("data"));

    //////            writer.Write(dataSize);

    //////            foreach (short s in samples)

    //////                writer.Write(s);

    //////        }

    //////    }//public static void WriteWavFile___SingleFile_ConstantSampleRate(...)

    //////}//class WavGenerator___MultiPitch_SingleFile_FixedDurations


    //////public class WavGenerator___MultiPitch_SingleFile_FixedDurations

    //////{

    //////    const int BaseSampleRate = 44100;

    //////    const int BitsPerSample = 16;

    //////    const int Channels = 1;


    //////    public static void function_to___ApplyPerRegionPitchShift_AND_SaveUnifiedWav(string gtampsFilePath, int numRegions)

    //////    {

    //////        var originalSamples = File.ReadLines(gtampsFilePath)

    //////                                  .Where(line => double.TryParse(line, out _))

    //////                                  .Select(double.Parse)

    //////                                  .ToList();


    //////        // Generate shifted versions

    //////        List<short> finalPcm = new List<short>();


    //////        for (int region = 0; region < numRegions; region++)

    //////        {

    //////            // Shruti step evenly from -22 to +22

    //////            int shrutiStep = -22 + (44 * region / numRegions);

    //////            double shiftFactor = Math.Pow(2, shrutiStep / 22.0);


    //////            var pitchShifted = ResamplePitchShift(originalSamples, shiftFactor);


    //////            // Now stretch/truncate pitch-shifted to same duration as original (i.e., same sample count)

    //////            var fixedDuration = StretchToLength(pitchShifted, originalSamples.Count);

    //////            finalPcm.AddRange(fixedDuration);

    //////        }


    //////        // Save to WAV

    //////        string outputPath = gtampsFilePath + $"__{numRegions}_Regions_MultiPitch_FIXED_T_Duration_output.wav";

    //////        WriteWavFile(outputPath, finalPcm, BaseSampleRate);


    //////        Console.WriteLine("Saved WAV: pitch-shifted regions, each fixed to original duration.");

    //////        System.Windows.Forms.MessageBox.Show("Output WAV: multi-pitch, all segments same duration.");

    //////    }


    //////    public static List<double> ResamplePitchShift(List<double> input, double shiftFactor)

    //////    {

    //////        int newLength = (int)(input.Count / shiftFactor);

    //////        List<double> result = new List<double>(newLength);


    //////        for (int i = 0; i < newLength; i++)

    //////        {

    //////            double srcIndex = i * shiftFactor;

    //////            int idx = (int)srcIndex;

    //////            double frac = srcIndex - idx;


    //////            double val = 0;

    //////            if (idx + 1 < input.Count)

    //////                val = (1 - frac) * input[idx] + frac * input[idx + 1];

    //////            else if (idx < input.Count)

    //////                val = input[idx];


    //////            result.Add(val);

    //////        }


    //////        return result;

    //////    }


    //////    public static List<short> StretchToLength(List<double> input, int targetLength)

    //////    {

    //////        List<short> output = new List<short>(targetLength);

    //////        double step = (double)(input.Count - 1) / (targetLength - 1);


    //////        for (int i = 0; i < targetLength; i++)

    //////        {

    //////            double srcIndex = i * step;

    //////            int idx = (int)srcIndex;

    //////            double frac = srcIndex - idx;


    //////            double val = 0;

    //////            if (idx + 1 < input.Count)

    //////                val = (1 - frac) * input[idx] + frac * input[idx + 1];

    //////            else if (idx < input.Count)

    //////                val = input[idx];


    //////            output.Add((short)(val * short.MaxValue));

    //////        }


    //////        return output;

    //////    }


    //////    public static void WriteWavFile(string filePath, List<short> samples, int sampleRate)

    //////    {

    //////        using (var stream = new FileStream(filePath, FileMode.Create))

    //////        using (var writer = new BinaryWriter(stream))

    //////        {

    //////            int byteRate = sampleRate * Channels * BitsPerSample / 8;

    //////            int dataSize = samples.Count * BitsPerSample / 8;


    //////            // RIFF header

    //////            writer.Write(Encoding.ASCII.GetBytes("RIFF"));

    //////            writer.Write(36 + dataSize);

    //////            writer.Write(Encoding.ASCII.GetBytes("WAVE"));


    //////            // fmt chunk

    //////            writer.Write(Encoding.ASCII.GetBytes("fmt "));

    //////            writer.Write(16);

    //////            writer.Write((short)1); // PCM

    //////            writer.Write((short)Channels);

    //////            writer.Write(sampleRate);

    //////            writer.Write(byteRate);

    //////            writer.Write((short)(Channels * BitsPerSample / 8));

    //////            writer.Write((short)BitsPerSample);


    //////            // data chunk

    //////            writer.Write(Encoding.ASCII.GetBytes("data"));

    //////            writer.Write(dataSize);

    //////            foreach (short s in samples)

    //////                writer.Write(s);

    //////        }

    //////    }

    //////}//public class WavGenerator___MultiPitch_SingleFile_FixedDurations




































    public class WavGenerator___MultiPitch___IT_GENERATES_SAME_PITCH_COPIES_ONLY____SingleFile_FixedDurations

    {

        //WE CANNOT CHANGE THE SAMPLE RATE FROM THE ORIGINAL GTAMPS SAMPLE RATES

        const int BaseSampleRate = 8000;//44100;//8000;// 16000;//8000;//44100; // or 8000, if desired

        const int BitsPerSample = 16;

        const int Channels = 1;


        public static void function_to___ApplyPerRegionPitchShift_AND_SaveUnifiedWav(string gtampsFilePath, int numRegions)

        {

            var originalSamples = File.ReadLines(gtampsFilePath)

                                      .Where(line => double.TryParse(line, out _))

                                      .Select(double.Parse)

                                      .ToList();


            List<short> finalPcm = ApplyPerRegionPitchShift(originalSamples, numRegions);


            //  string outputPath = gtampsFilePath + $"___{numRegions}_Regions_MultiPitch_FIXED_T_Duration_output.wav";

            string outputPath = gtampsFilePath + $"___{numRegions}_Regions_SAMEPitchCOPY_FIXED_T_Duration_output.wav";

            WriteWavFile(outputPath, finalPcm, BaseSampleRate);


            Console.WriteLine("Unified WAV written with pitch-shifted regions (duration preserved).");

            System.Windows.Forms.MessageBox.Show("WAV with multiple pitches and fixed durations saved:\n" + outputPath);

        }//public static void function_to___ApplyPerRegionPitchShift_AND_SaveUnifiedWav


        public static List<short> ApplyPerRegionPitchShift(List<double> original, int numRegions)

        {

            //  double segmentDurationSec = original.Count / (double)BaseSampleRate;



            // double segmentDurationSec = (original.Count* numRegions) / (double)BaseSampleRate;

            double segmentDurationSec = original.Count / (double)BaseSampleRate; //WHEN I DO THIS THEN ALL ARE PLAYING WITH SAME FREWQUENCY

            List<short> output = new List<short>();


            for (int region = 0; region < numRegions; region++)

            {

//int shrutiStep = -22 + (44 * region / numRegions);

                int shrutiStep = -(int)(numRegions/2) + (44 * region / numRegions);


                double shiftFactor = Math.Pow(2, shrutiStep / 22.0);


                var pitchShifted = ResamplePitchShift(original, shiftFactor);


                int desiredSampleCount = (int)(segmentDurationSec * BaseSampleRate);

                var adjusted = StretchToLength(pitchShifted, desiredSampleCount);


                output.AddRange(adjusted);

            }//for (int region = 0; region < numRegions; region++)


            return output;

        }//public static List<short> ApplyPerRegionPitchShift


        public static List<double> ResamplePitchShift(List<double> input, double shiftFactor)

        {

            int newLength = (int)(input.Count / shiftFactor);

            var result = new List<double>(newLength);


            for (int i = 0; i < newLength; i++)

            {

                double srcIndex = i * shiftFactor;

                int idx = (int)srcIndex;

                double frac = srcIndex - idx;


                double val = 0;

                if (idx + 1 < input.Count)

                    val = (1 - frac) * input[idx] + frac * input[idx + 1];

                else if (idx < input.Count)

                    val = input[idx];


                result.Add(val);

            }//for (int i = 0; i < newLength; i++)


            return result;

        }//public static List<double> ResamplePitchShift


        public static List<short> StretchToLength(List<double> input, int targetLength)

        {

            var output = new List<short>(targetLength);

            double step = (double)(input.Count - 1) / (targetLength - 1);
















            for (int i = 0; i < targetLength; i++)

            {

                double srcIndex = i * step;

                int idx = (int)srcIndex;

                double frac = srcIndex - idx;


                double val = 0;

                if (idx + 1 < input.Count)

                {

                    val = (1 - frac) * input[idx] + frac * input[idx + 1];

                }

                else if (idx < input.Count)

                {

                    val = input[idx];

                }


                short pcm = (short)(val * short.MaxValue);

                output.Add(pcm);

            }


            return output;

        }//public static List<short> StretchToLength


        public static void WriteWavFile(string filePath, List<short> samples, int sampleRate)

        {

            using (var stream = new FileStream(filePath, FileMode.Create))

            using (var writer = new BinaryWriter(stream))

            {

                int byteRate = sampleRate * Channels * BitsPerSample / 8;

                int dataSize = samples.Count * BitsPerSample / 8;


                // RIFF header

                writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                writer.Write(36 + dataSize);

                writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                // fmt chunk

                writer.Write(Encoding.ASCII.GetBytes("fmt "));

                writer.Write(16);

                writer.Write((short)1); // PCM

                writer.Write((short)Channels);

                writer.Write(sampleRate);

                writer.Write(byteRate);

                writer.Write((short)(Channels * BitsPerSample / 8));

                writer.Write((short)BitsPerSample);


                // data chunk

                writer.Write(Encoding.ASCII.GetBytes("data"));

                writer.Write(dataSize);

                foreach (short s in samples)

                    writer.Write(s);

            }

        }//public static void WriteWavFile

    }//public class WavGenerator___MultiPitch_SingleFile_FixedDurations




    public class WavGenerator___Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis

    {

        const int SampleRate = 8000;

        const int BitsPerSample = 16;

        const int Channels = 1;

        const double Pi = Math.PI;


        public static void SAANS___WavGenerator___Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis___Main(string gtamps_filesnames)

        {

            string inputPath = gtamps_filesnames;// "your_file_path_here.txt";

           


            // Read float samples

            var samples = File.ReadLines(inputPath)

                              .Where(line => double.TryParse(line, out _))

                              .Select(double.Parse)

                              .ToList();


            var allShifted = new List<short>();


            for (int r = 1; r <= 22; r++)

            {

                double shiftFactor = Math.Pow(2, r / 22.0);

                var shifted = ResampleWithFrequencyShift(samples, shiftFactor);

                allShifted.AddRange(shifted);

            }//for (int r = 1; r <= 22; r++)



            string outputPath = inputPath + "___22_times_8000hZ_16_BITS_PCMS_"+allShifted.Count.ToString() + "_output.wav";


            WriteWavFile(outputPath, allShifted);

            Console.WriteLine("WAV file written to: " + outputPath);

        }//public static void SAANS___WavGenerator___Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis___Main(STRING gtamps_filesnames)


        public static List<short> ResampleWithFrequencyShift(List<double> samples, double shiftFactor)

        {

            int newLength = (int)(samples.Count / shiftFactor);

            var shifted = new List<short>(newLength);


            for (int i = 0; i < newLength; i++)

            {

                double srcIndex = i * shiftFactor;

                int idx = (int)srcIndex;

                double frac = srcIndex - idx;


                double value = 0;

                if (idx + 1 < samples.Count)

                    value = (1 - frac) * samples[idx] + frac * samples[idx + 1];

                else if (idx < samples.Count)

                    value = samples[idx];


                short pcmVal = (short)(value * short.MaxValue);

                shifted.Add(pcmVal);

            }//for (int i = 0; i < newLength; i++)


            return shifted;

        }//public static List<short> ResampleWithFrequencyShift(List<double> samples, double shiftFactor)


        public static void WriteWavFile(string filePath, List<short> samples)

        {

            using (var stream = new FileStream(filePath, FileMode.Create))

            using (var writer = new BinaryWriter(stream))

            {

                int byteRate = SampleRate * Channels * BitsPerSample / 8;

                int dataSize = samples.Count * BitsPerSample / 8;


                // RIFF header

                writer.Write(Encoding.ASCII.GetBytes("RIFF"));

                writer.Write(36 + dataSize);

                writer.Write(Encoding.ASCII.GetBytes("WAVE"));


                // fmt subchunk

                writer.Write(Encoding.ASCII.GetBytes("fmt "));

                writer.Write(16); // PCM

                writer.Write((short)1); // AudioFormat = PCM

                writer.Write((short)Channels);

                writer.Write(SampleRate);

                writer.Write(byteRate);

                writer.Write((short)(Channels * BitsPerSample / 8));

                writer.Write((short)BitsPerSample);


                // data subchunk

                writer.Write(Encoding.ASCII.GetBytes("data"));

                writer.Write(dataSize);

                foreach (short s in samples)

                { writer.Write(s); }

            }//using (var writer = new BinaryWriter(stream))

        }//public static void WriteWavFile(string filePath, List<short> samples)

    }//public class WavGenerator___Reads_GTAMPS_MONO_8000_Hz_Samples_16_bits_no_3rd_party_apis







}//namespace SAAN_FRESH___RAW_NON_APIS_WAVES_TO_SHRUTIES_COPIER_GPTS



No comments:

Post a Comment