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