Sound wav to image, it is possible ?

Posted By: Ice2642

Sound wav to image, it is possible ? - 08/31/20 12:26

Hello,

Sorry about my English,

I wold like to know if it is possible lite-C get a sound and display it in waves on screen, like VU meter to show the music intensity.

Any one can give a example of code to made this?

Thank you n advance.

Best regards,

Marcio
Posted By: Dooley

Re: Sound wav to image, it is possible ? - 08/31/20 21:54

I was never able to do anything like that. You might look into the windows.h commands to see if there is anything that can interpret sounds...
Posted By: txesmi

Re: Sound wav to image, it is possible ? - 09/01/20 10:37

Hi,
you can access the buffer of a sound but a real time analysis would be pretty intensive. Take into account that it would play hundreds of samples between frames.

Code
#include <acknex.h>
#include <d3d9.h>

#define PRAGMA_PATH "%EXE_DIR%\\templates\\sounds"

/*
typedef struct DSBUFFERDESC {
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwBufferBytes;
    DWORD dwReserved;
    LPWAVEFORMATEX lpwfxFormat;
    GUID guid3DAlgorithm;
} DSBUFFERDESC;

typedef struct {
  WORD  wFormatTag;
  WORD  nChannels;
  DWORD nSamplesPerSec;
  DWORD nAvgBytesPerSec;
  WORD  nBlockAlign;
  WORD  wBitsPerSample;
  WORD  cbSize;
} WAVEFORMATEX;
*/

SOUND *snd = "shot4.wav";
//SOUND *snd = "tdestroyed.wav";
//SOUND *snd = "#1";

var step = 70;

void draw8bits(var posStart, short *bit, int length)
{
	VECTOR vec;
	vec_set(&vec, vector(posStart, 150, 0));
	draw_line(&vec, NULL, 100);
	draw_line(&vec, COLOR_WHITE, 100);
	
	var posX = posStart;
	var posY = 250;
	int i = 0;
	for(; i < length; i += 2, bit += 1)
	{
		vec.x += 1;
		vec.y = 150.0 + (*bit - 32896.0) / 32896.0 * 100.0;
		if(vec.x > 0)
			draw_line(&vec, COLOR_WHITE, 100);
		
		if(posX > 0)
			draw_text(str_for_int(NULL, *bit), posX, posY, COLOR_WHITE);
		
		posY += 8;
		if(!(vec.x % step))
		{
			posY = 250;
			posX += step;
			if(posX > screen_size.x)
				break;
		}
	}
	draw_line(&vec, NULL, 100);	
}

void draw16bits(var posStart, long *bit, int length)
{
	VECTOR vec;
	vec_set(&vec, vector(posStart, 150, 0));
	draw_line(&vec, NULL, 100);
	draw_line(&vec, COLOR_WHITE, 100);
	
	var posX = posStart;
	var posY = 250;
	int i = 0;
	for(; i < length; i += 4, bit += 1)
	{
		vec.x += 1;
		vec.y = 150.0 + *bit / 2147483648.0 * 100.0;
		if(vec.x > 0)
			draw_line(&vec, COLOR_WHITE, 100);
		
		if(posX > 0)
			draw_text(str_for_int(NULL, *bit), posX, posY, COLOR_WHITE);
		
		posY += 8;
		if(!(vec.x % step))
		{
			posY = 250;
			posX += step;
			if(posX > screen_size.x)
				break;
		}
	}
	draw_line(&vec, NULL, 100);	
}

void main()
{
	video_mode = 10;
	fps_max = 60;
	
	wait(1);
	draw_textmode("Courier New", 0, 12, 100);
	
	var posStart = 1;
	
	var keyL = 0;
	var keyR = 0;
	var timer = 0;
	
	while(!key_esc)
	{
		DSBUFFERDESC *dsBufferDesc;
		byte** pSampleBuffer;
		snd_buffer(snd, &dsBufferDesc, &pSampleBuffer);
		
		// sound data
		draw_text(str_printf(NULL, "size:         %d", dsBufferDesc->dwSize),                       0,  0, COLOR_WHITE);
		draw_text(str_printf(NULL, "buffer bytes: %d", dsBufferDesc->dwBufferBytes),                0, 10, COLOR_WHITE);
		
		draw_text(str_printf(NULL, "channels:     %d", dsBufferDesc->lpwfxFormat.nChannels),      200,  0, COLOR_WHITE);
		draw_text(str_printf(NULL, "bytes sample: %d", dsBufferDesc->lpwfxFormat.wBitsPerSample), 200, 10, COLOR_WHITE);
		draw_text(str_printf(NULL, "bytes sec:    %d", dsBufferDesc->lpwfxFormat.nSamplesPerSec), 200, 20, COLOR_WHITE);
		
		// move drawing
		if(key_cul && !keyL)
		{
			timer = 0;
			posStart -= step;
		}
		else if(key_cul)
		{
			timer += time_step;
			if(timer > 2)
			{
				timer = 0;
				posStart -= step;
			}
		}
		keyL = key_cul;
		
		if(key_cur && !keyR)
		{
			timer = 0;
			posStart += step;
		}
		else if(key_cur)
		{
			timer += time_step;
			if(timer > 2)
			{
				timer = 0;
				posStart += step;
			}
		}
		keyR = key_cur;
		
		// draw
		switch((int)dsBufferDesc->lpwfxFormat.wBitsPerSample)
		{
			case 8:
				draw8bits(posStart, *pSampleBuffer, dsBufferDesc->dwBufferBytes);
				break;
			case 16:
				draw16bits(posStart, *pSampleBuffer, dsBufferDesc->dwBufferBytes);
				break;
			default:
				draw_text("Unknown format!", 0, 250, COLOR_WHITE);
		}
		
		wait(1);
	}
	
	sys_exit(NULL);
}


Salud!
Posted By: Dooley

Re: Sound wav to image, it is possible ? - 09/01/20 14:48

Wow!
Maybe it would be possible to get less samples, like 30 samples a second. That would possibly allow drawing the graph in real-time as the sound is playing.
This is amazing, and beyond what I thought 3D Gamestudio was capable of. I am always surprised when I see how versatile this engine is...
Posted By: Ice2642

Re: Sound wav to image, it is possible ? - 09/01/20 17:44


Originally Posted by txesmi
Hi,
you can access the buffer of a sound but a real time analysis would be pretty intensive. Take into account that it would play hundreds of samples between frames.

Code
#include <acknex.h>
#include <d3d9.h>

#define PRAGMA_PATH "%EXE_DIR%\\templates\\sounds"

/*
typedef struct DSBUFFERDESC {
    DWORD dwSize;
    DWORD dwFlags;
    DWORD dwBufferBytes;
    DWORD dwReserved;
    LPWAVEFORMATEX lpwfxFormat;
    GUID guid3DAlgorithm;
} DSBUFFERDESC;

typedef struct {
  WORD  wFormatTag;
  WORD  nChannels;
  DWORD nSamplesPerSec;
  DWORD nAvgBytesPerSec;
  WORD  nBlockAlign;
  WORD  wBitsPerSample;
  WORD  cbSize;
} WAVEFORMATEX;
*/

SOUND *snd = "shot4.wav";
//SOUND *snd = "tdestroyed.wav";
//SOUND *snd = "#1";

var step = 70;

void draw8bits(var posStart, short *bit, int length)
{
	VECTOR vec;
	vec_set(&vec, vector(posStart, 150, 0));
	draw_line(&vec, NULL, 100);
	draw_line(&vec, COLOR_WHITE, 100);
	
	var posX = posStart;
	var posY = 250;
	int i = 0;
	for(; i < length; i += 2, bit += 1)
	{
		vec.x += 1;
		vec.y = 150.0 + (*bit - 32896.0) / 32896.0 * 100.0;
		if(vec.x > 0)
			draw_line(&vec, COLOR_WHITE, 100);
		
		if(posX > 0)
			draw_text(str_for_int(NULL, *bit), posX, posY, COLOR_WHITE);
		
		posY += 8;
		if(!(vec.x % step))
		{
			posY = 250;
			posX += step;
			if(posX > screen_size.x)
				break;
		}
	}
	draw_line(&vec, NULL, 100);	
}

void draw16bits(var posStart, long *bit, int length)
{
	VECTOR vec;
	vec_set(&vec, vector(posStart, 150, 0));
	draw_line(&vec, NULL, 100);
	draw_line(&vec, COLOR_WHITE, 100);
	
	var posX = posStart;
	var posY = 250;
	int i = 0;
	for(; i < length; i += 4, bit += 1)
	{
		vec.x += 1;
		vec.y = 150.0 + *bit / 2147483648.0 * 100.0;
		if(vec.x > 0)
			draw_line(&vec, COLOR_WHITE, 100);
		
		if(posX > 0)
			draw_text(str_for_int(NULL, *bit), posX, posY, COLOR_WHITE);
		
		posY += 8;
		if(!(vec.x % step))
		{
			posY = 250;
			posX += step;
			if(posX > screen_size.x)
				break;
		}
	}
	draw_line(&vec, NULL, 100);	
}

void main()
{
	video_mode = 10;
	fps_max = 60;
	
	wait(1);
	draw_textmode("Courier New", 0, 12, 100);
	
	var posStart = 1;
	
	var keyL = 0;
	var keyR = 0;
	var timer = 0;
	
	while(!key_esc)
	{
		DSBUFFERDESC *dsBufferDesc;
		byte** pSampleBuffer;
		snd_buffer(snd, &dsBufferDesc, &pSampleBuffer);
		
		// sound data
		draw_text(str_printf(NULL, "size:         %d", dsBufferDesc->dwSize),                       0,  0, COLOR_WHITE);
		draw_text(str_printf(NULL, "buffer bytes: %d", dsBufferDesc->dwBufferBytes),                0, 10, COLOR_WHITE);
		
		draw_text(str_printf(NULL, "channels:     %d", dsBufferDesc->lpwfxFormat.nChannels),      200,  0, COLOR_WHITE);
		draw_text(str_printf(NULL, "bytes sample: %d", dsBufferDesc->lpwfxFormat.wBitsPerSample), 200, 10, COLOR_WHITE);
		draw_text(str_printf(NULL, "bytes sec:    %d", dsBufferDesc->lpwfxFormat.nSamplesPerSec), 200, 20, COLOR_WHITE);
		
		// move drawing
		if(key_cul && !keyL)
		{
			timer = 0;
			posStart -= step;
		}
		else if(key_cul)
		{
			timer += time_step;
			if(timer > 2)
			{
				timer = 0;
				posStart -= step;
			}
		}
		keyL = key_cul;
		
		if(key_cur && !keyR)
		{
			timer = 0;
			posStart += step;
		}
		else if(key_cur)
		{
			timer += time_step;
			if(timer > 2)
			{
				timer = 0;
				posStart += step;
			}
		}
		keyR = key_cur;
		
		// draw
		switch((int)dsBufferDesc->lpwfxFormat.wBitsPerSample)
		{
			case 8:
				draw8bits(posStart, *pSampleBuffer, dsBufferDesc->dwBufferBytes);
				break;
			case 16:
				draw16bits(posStart, *pSampleBuffer, dsBufferDesc->dwBufferBytes);
				break;
			default:
				draw_text("Unknown format!", 0, 250, COLOR_WHITE);
		}
		
		wait(1);
	}
	
	sys_exit(NULL);
}


Salud!


This help very much, thank you !!! laugh
Posted By: Superku

Re: Sound wav to image, it is possible ? - 09/03/20 07:52

You could pre-process the sound once at game start and save the result in some struct. Depending on the sound's sample rate and the desired display frequency (like 60fps for the visualizer) you could then average sampleCountPerSecond/60 samples into one (and optionally save min and max values or even separate into different frequencies).
Posted By: Ice2642

Re: Sound wav to image, it is possible ? - 09/03/20 19:44

Good idea. but for the speed I think the most viable will be to create a dll just for that. I was planning to make a simple little program like some kind of simple Protracker of the commodore Amiga that you load a wav as a sampler and create a sequence of sounds forming a song amd when it play you see the wavs in VU meter. But more simple, just for fun.
© 2024 lite-C Forums