Wednesday, June 4, 2025

FREQUENCY WISE PANNING ON WAV FILES 66 SHRUTIS COPIERS

   public class TO_DO_PAN_WITH_FREQUENCY_CHANGES_44100_SPS_2_CHANNELS___NEW_KIND_OF_ShrutiResamplerGenerator___33_PLUS_33_66_COPIES_PLAYING_ALL_SAMPLES___GPT

    {

        public static void GenerateShrutiVariants___GPT(string inputWavPath, string outputWavPath)

        {

            float[] sourceSamples = ReadWavMonoAsFloats(inputWavPath, out int sourceRate);

            int outputRate = 8000;//THE OUTPUT IS OK BUT TOO HEAVY FILES  44100;

            double originalFrequency = 440.0;

            double durationSec = sourceSamples.Length / (double)sourceRate;

            double totalCycleProduct = originalFrequency * durationSec;


            using (FileStream fs = new FileStream(outputWavPath, FileMode.Create))

            using (BinaryWriter bw = new BinaryWriter(fs))

            {

                WriteWavHeaderPlaceholder(bw, outputRate, 2);


                for (int i = -33; i <= 32; i++)

                {

                    double semitoneShift = i * (1.0 / 3);

                    double freqMultiplier = Math.Pow(2, semitoneShift / 12.0);

                    double newFreq = originalFrequency * freqMultiplier;

                    double newDuration = totalCycleProduct / newFreq;

                    int newSampleCount = (int)(newDuration * outputRate);


                    float[] resampled = ResampleWithFactor(sourceSamples, newSampleCount);


                    int lastPan = 0;

                    int start = 0;


                    for (int j = 1; j < resampled.Length; j++)

                    {

                        if ((resampled[j - 1] >= 0 && resampled[j] < 0) || (resampled[j - 1] < 0 && resampled[j] >= 0))

                        {

                            for (int k = start; k < j; k++)

                            {

                                float l = lastPan == 0 ? resampled[k] : 0;

                                float r = lastPan == 1 ? resampled[k] : 0;

                                WriteStereoSample(bw, l, r);

                            }

                            lastPan = 1 - lastPan;

                            start = j;

                        }

                    }

                    for (int k = start; k < resampled.Length; k++)

                    {

                        float l = lastPan == 0 ? resampled[k] : 0;

                        float r = lastPan == 1 ? resampled[k] : 0;

                        WriteStereoSample(bw, l, r);

                    }

                }


                long fileLength = fs.Position;

                PatchWavHeader(bw, outputRate, 2, (int)(fileLength - 44));

            }


            Console.WriteLine("Stereo 66 shruti-pitched variants with ear-swing effect generated.");

            MessageBox.Show("Done: Stereo shruti variants created\n" + outputWavPath);

        }


        public static float[] ResampleWithFactor(float[] input, int targetLength)

        {

            float[] result = new float[targetLength];

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

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

            {

                double pos = i * step;

                int idx = (int)pos;

                double frac = pos - idx;

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

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

                    : input[idx];

            }

            return result;

        }


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

        {

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

            {

                br.BaseStream.Seek(0, SeekOrigin.Begin);

                br.ReadBytes(12);

                int channels = 1;

                sampleRate = 44100;

                int bitsPerSample = 16;


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

                {

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

                    int chunkSize = br.ReadInt32();


                    if (chunkID == "fmt ")

                    {

                        br.ReadInt16();

                        channels = br.ReadInt16();

                        sampleRate = br.ReadInt32();

                        br.ReadInt32();

                        br.ReadInt16();

                        bitsPerSample = br.ReadInt16();

                        if (chunkSize > 16)

                            br.ReadBytes(chunkSize - 16);

                    }

                    else 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();

                        }

                        return samples;

                    }

                    else

                    {

                        br.ReadBytes(chunkSize);

                    }

                }

            }

            sampleRate = 44100;

            return new float[0];

        }


        public static void WriteStereoSample(BinaryWriter bw, float left, float right)

        {

            short l = (short)(Math.Max(-1f, Math.Min(1f, left)) * 32767);

            short r = (short)(Math.Max(-1f, Math.Min(1f, right)) * 32767);

            bw.Write(l);

            bw.Write(r);

        }


        public static void WriteWavHeaderPlaceholder(BinaryWriter bw, int sampleRate, int channels)

        {

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

            bw.Write(0); // Placeholder for file size

            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);

            int byteRate = sampleRate * channels * 2;

            short blockAlign = (short)(channels * 2);

            bw.Write(byteRate);

            bw.Write(blockAlign);

            bw.Write((short)16);

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

            bw.Write(0); // Placeholder for data chunk size

        }


        public static void PatchWavHeader(BinaryWriter bw, int sampleRate, int channels, int dataSize)

        {

            bw.Seek(4, SeekOrigin.Begin);

            bw.Write(36 + dataSize);

            bw.Seek(40, SeekOrigin.Begin);

            bw.Write(dataSize);

        }


        public static float[] StretchToLength(float[] input, int targetLength)

        {

            return ResampleWithFactor(input, targetLength);

        }










    }//public class TO_DO_PAN_WITH_FREQUENCY_CHANGES_44100_SPS_2_CHANNELS___NEW_KIND_OF_ShrutiResamplerGenerator___33_PLUS_33_66_COPIES_PLAYING_ALL_SAMPLES___GPT

 

No comments:

Post a Comment