29 June 2007

OpenAL - Test #1

Well, it wasn't in my plans to to this this evening... This test wasn't planned at all :D But since I had headache this evening, I didn't feel the right mood for studying :P
So, I got disconnected from the IM client (all of them), took a tutorial and the reference of OpenAL and I tried to make a sound.

The reason is simple: in these days I'm getting into nerdcore music (notabily, 8 Bit Weapon :D So I absolutely wanted to create my own 8-bit sound (and, you know, once you get the sound you want, you did the most).

So, OpenAL was my way.

I'm not an audio expert, I really find sampling, frequencies and so on difficult to get (well, actually it isn't at all :D It's only that I found a bit difficult to build a PCM sine wave from nothing. Then I found out that my problem is only that "buffer frequency" was the "sampling frequency", not the "frequency of my signal" (obviusly)).

So, this is my test. Quite short for 2 hours of works! (or more). Well, it was my first time :D Now I got it, so next works should be more easy.

#if 0
#!/bin/sh

FILE=`basename $0 | sed "s/\.[Cc].*$//"`
EXT=` basename $0 | sed "s/^.*\.\([Cc].*\)$/\1/"`

CC="gcc -g -Wall -Wextra -pedantic -std=c99"

$CC $FILE.$EXT -o $FILE -lm -lopenal -lalut

exit
#endif

#include
#include

#include

#define D2R 0.0174532925

#include
#include

#include

int main(int argc, char **argv)
{
// Initialize a context
alutInit(&argc, argv);
// Clean error flags
alGetError();

// Allocate buffers
ALuint buffer[1];

// Create the buffers
alGenBuffers(1, buffer);
if (alGetError() != AL_NO_ERROR)
return -1;

// Build the data
ALenum format = AL_FORMAT_MONO8;
ALsizei size;
ALsizei freq;
ALboolean loop;
ALvoid *data;

char file[512];
printf("Please insert a path for the file to play (space for none), enter to confirm\n");
fgets(file, 512, stdin);
if (file[0] < ' ') // The first char is not a string valid char (i.e. empty string)
// Load from extern file
alutLoadWAVFile(file, &format, &data, &size, &freq, &loop);
else {
printf("Generating sine wave on user parameters\n");
// Generate using math
// We want a note of 440 Hz. 32 samples for each oscillation
// for 1 seconds, means 440*32 bytes
unsigned char *sineWave;
int samples,
frequency;
printf("Which frequency? ");
scanf("%d", &frequency);
printf("How many samples for the wave? [try me between 2 and 16] ");
scanf("%d", &samples);
freq = samples * frequency;
printf("We will use a sampling frequency equal to the signal frequency:\n"
"sgnFreq * sgnSampl = %d * %d = %d\n", frequency, samples, freq);
size = freq; // We don't need an higher frequency than the signal
if (!(sineWave = malloc(size)))
return -2;

for (int i = 0; i < size; ++i) {
float x = i * 360.0 / (float)samples;
sineWave[i] = sin(x * D2R) * 128 + 128; // Clamp to [0,255]
// printf("Sinewave[%d] = %d\n", i, sineWave[i]);
}
data = sineWave;
}

printf("Values: fmt: %d siz %d freq %d\n", format, size, freq);
alBufferData(buffer[0], format, data, size, freq);

// Setup sources
ALuint source[1];
alGenSources(1, source);
if (alGetError() != AL_NO_ERROR)
return -3;

float srcPos[] = {3.0, 0.0, -3.0};

alSourcei(source[0], AL_BUFFER, buffer[0]);
alSourcefv(source[0], AL_POSITION, srcPos);

float lstPos[] = {0.0, 0.0, 0.0};
alListenerfv(AL_POSITION, lstPos);

alSourcePlay(source[0]);

// Wait until termination of the sound
sleep(2);

// Clear the things
alDeleteSources(1, source);
alDeleteBuffers(1, buffer);
alutExit();

return EXIT_SUCCESS;
}

The scope of this isn't really the use of openal (which is really simple), but the construction of a digital signal. In detail, you can actually understand how changing sampling frequency affect the riproduction of the signal.

Stay --sync

1 commenti:

  1. Good idea, OpenAL are cool!

    They deserve more attention that I gave so far... I've just learnt how to create buffers and play/move/pitch them.

    Maybe this summer I'll spend some week working on them! =)
    ReplyDelete