How to stretch to nearest or interpolate inbetween pixels in a logarithmic audio spectrum converted to a picture in Visual Studio using C# Console #2820
Replies: 2 comments 13 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
I'm trying to program a code to convert an audio to an image spectrogram in the scale of logarithmic, but black lines come up. I search for help, I ask 4 different AI chatbots for help, and though it gave me some correct code, it gave wrong or broken code with this problem, Microsoft's Forum told me to go here, and running out of options, I have no choice but to ask for help here. Here is my code;
`using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using NAudio.Wave;
using MathNet.Numerics;
using MathNet.Numerics.IntegralTransforms;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
class Program
{
static void Main(string[] args)
{
string spectrogramPath = @"C:\Users\seven\Music\spectrogram.bmp"; // Path for the spectrogram image
string modifiedSpectrogramPath = @"C:\Users\seven\Music\modified_spectrogram.bmp"; // Path for modified spectrogram
using (var reader = new AudioFileReader(filePath))
{
var samples = new float[reader.Length / sizeof(float)];
reader.Read(samples, 0, samples.Length);
var spectrogram = GetLogSpectrogram(samples, reader.WaveFormat.SampleRate, fftLength);
SaveSpectrogramImage(spectrogram, fftLength / 2, spectrogramPath);
}
ScalePart(@"C:\Users\seven\Music\spectrogram.bmp", modifiedSpectrogramPath);
}
static double[,] GetLogSpectrogram(float[] samples, int sampleRate, int fftLength)
{
int numSpectrogramRows = fftLength / 2;
int numSpectrogramColumns = (samples.Length / fftLength) * 2;
double[,] spectrogram = new double[numSpectrogramRows, numSpectrogramColumns];
for (int i = 0; i < numSpectrogramColumns; i++)
{
int offset = i * fftLength / 2;
if (offset + fftLength >= samples.Length)
break;
var buffer = samples.Skip(offset).Take(fftLength).Select(s => new Complex32(s, 0)).ToArray();
Fourier.Forward(buffer, FourierOptions.NoScaling);
for (int j = 0; j < numSpectrogramRows; j++)
{
spectrogram[j, i] = 20 * Math.Log10(Math.Max(buffer[j].Magnitude, 1e-10));
}
}
return spectrogram;
}
static void SaveSpectrogramImage(double[,] spectrogram, int height, string outputPath)
{
int width = spectrogram.GetLength(1);
using (Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb))
{
double max = spectrogram.Cast().Max();
double min = spectrogram.Cast().Min();
double gamma = 3;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int value = (int)((spectrogram[y, x] - min) / (max - min) * 255);
value = (int)(255 * Math.Pow(value / 255.0, gamma)); // Apply gamma correction
System.Drawing.Color color = System.Drawing.Color.FromArgb(value, value, value);
bitmap.SetPixel(x, height - y - 1, color);
}
}
bitmap.Save(outputPath, ImageFormat.Bmp);
}
}
static void ScalePart(string inputPath, string outputPath)
{
using (var image = SixLabors.ImageSharp.Image.Load(inputPath))
{
int originalHeight = image.Height;
using (var outputImage = new Image(image.Width, originalHeight))
{
for (int x = 0; x < image.Width; x++)
{
for (int y = 0; y < originalHeight; y++)
{
double logScaleY = Math.Log(y + 1) / Math.Log(originalHeight + 1); // Normalized logarithm
int newY = (int)(logScaleY * (originalHeight - 1)); // Transform Y to new position
if (newY < originalHeight)
{
var color = image[x, originalHeight - y - 1]; // The image is flipped for coordinate compatibility
outputImage[x, newY] = color;
}
}
}
outputImage.Save(outputPath);
}
}
}
}`
The black bars at the top I want removed, either by interpolating inbetween lines or stretching the nearest pixel vertically.
AI was giving me such a hard time, I asked Microsoft at after 1:45AM this morning for help after almost a day and a half (give or take the breaks) barely getting it to work at all, even with an alternative, FFMPEG. Now, it has been closer to 2 Days.
This is possible, right? Because even Image Editors can pixelate or interpolate pictures, and warp them in such ways. What is the full code (In this message and what I am trying to achieve)?
If you want to know, I am trying to convert a sound to a logarithmic frequency scale in an image, flip it vertically, redo the frequency, and convert it back to audio, so the pitch is reversed. Many AIs said I could shift the pitch, or resample, or reverse, or flip linearly (Hertz), or use Invert to flip the waveform, but that is not what I want. I basically want to invert the pitch.
These lines might result in additional weird sound, but I want to remove these black stripes and just flip it logarithmically.
Help would be appreciated. If this is the wrong category, please move it to the appropriate category and give me a link to the new path. If someone asked the same thing, please link me there before closing, but I doubt someone asked this question because the AIs programming might not have what I am asking, because nobody is asking.
Thank you for helping.
Quote Mark; Because reverse is slower than forward; it is speed in the negative.
Beta Was this translation helpful? Give feedback.
All reactions