How to create waveform texture from AudioClip?

Hello,

I’ve been trying to generate the waveform from the audioclip to a texture, but I ran into one issue.

For some reason the waveform is not drawn entirely. I created this really simple sound to check and it appears that it didn’t generated waveform from the entire track, but only from half or less of the track. Could someone give some help on this? Thank you

I found the code below from here: How to generate waveform from AudioClip? - Questions & Answers - Unity Discussions

Code:

public Texture2D PaintWaveformSpectrum(AudioClip audio, float saturation, int width, int height, Color col) {
     Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false);
     float[] samples = new float[audio.samples];
     float[] waveform = new float[width];
     audio.GetData(samples, 0);
     int packSize = ( audio.samples / width ) + 1;
     int s = 0;
     for (int i = 0; i < audio.samples; i += packSize) {
         waveform ~~= Mathf.Abs(samples*);*~~

s++;
}

for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
tex.SetPixel(x, y, Color.black);
}
}

for (int x = 0; x < waveform.Length; x++) {
for (int y = 0; y <= waveform[x] * ((float)height * .75f); y++) {
tex.SetPixel(x, ( height / 2 ) + y, col);
tex.SetPixel(x, ( height / 2 ) - y, col);
}
}
tex.Apply();

return tex;
}
And used it like this:
public class Draw : MonoBehaviour
{
public int width = 500;
public int height = 100;
public Color waveformColor = Color.green;
public Color bgColor = Color.green;
public float sat = .5f;

[SerializeField] Image img;
[SerializeField] AudioClip clip;

void Start()
{
Texture2D texture = TestAudioWaveformDraw.PaintWaveformSpectrum(clip, sat, width, height, waveformColor, bgColor);
img.overrideSprite = Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height), new Vector2(0.5f, 0.5f));
}
}
Result:
Generated Waveform:
[133346-generatedtexture.png|133346]~~
Actual Waveform:
~~
[133347-actualsound.png*|133347]*
~~*
~~*

Alright so apparently turning your tracks to be ‘Force to Mono’ solved my issue.
The solution was suggested by the user (@Kurt-Dekker) in the forum post: https://forum.unity.com/threads/how-to-create-waveform-texture-from-audioclip.631480/

I used this code and ran into some issues.
So for people trying to use this here are 2 advices:


First you won’t have to ‘Force to Mono’ but simply multiply ‘audio.samples’ with ‘audio.channels’ like this: float[] samples = new float[audio.samples * audio.channels]; and then later on instead of using ‘audio.samples’ everywhere simply use ‘samples.Length’ like here for example: int packSize = ( samples.Length/ width ) + 1;.


Second tip is not to use this:

int packSize = ( audio.samples / width ) + 1;
int s = 0;
for (int i = 0; i < audio.samples; i += packSize) 
{
     waveform ~~= Mathf.Abs(samples*);*~~

s++;
}
And instead go with this:
float packSize = ((float)samples.Length / (float)width);
int s = 0;
for (float i = 0; Mathf.RoundToInt(i) < samples.Length && s < waveform.Length; i += packSize)
{
waveform = Mathf.Abs(samples[Mathf.RoundToInt(i)]);
s++;
}
The problem with the ‘int packSize’ is that as it’s rounded the waveform won’t be scaled perfectly and won’t be perfectly aligned to the actual song but a bit compressed.