0
101 Feb 28, 2007 at 09:18

How do I change the speed of a played wav file in OpenAL? There doesn’t seem to be a function nor any examples for it.
How do I change the posistion in the stream of the wav file? (for example, start playing at the middle of the wav file)

Frank

#### 6 Replies

0
101 Mar 01, 2007 at 20:05

This almost seems too obvious to me, and since no one’s made a reply, I’ll take a shot and risk sounding stupid… but here’s a go at it.

Take the sample of a piece of audio. To play the audio fast, you could loop through half the size of the array of the sample, and play every other bit. You could speed up more and more by increasing the amount you increment through the sample.

You could double the values to slow it down. So you would push each item in to an array twice in a row to double the size of the sample and play that back, elongating the information should have the effect of slowing down.

 becomes - - - - - ->

 (to speed up)

 becomes

 (to slow down)

Bam! Sound like an idea worth trying? Maybe just for fun?

You could store the samples in memory until your done processing, then play it back. Or store it in a .wav file, what ever you decide. It can be done.

Hope this helps… at all, or gives you ideas. enjoy!

(You could get fancy and compare the even/odd samples and do some kind of averaging to maintain SOME information between splicing/stretching. Imagine anti-aliasing in graphics applied to audio over time. Seems like a good idea huh? Maybe… I’ll poke around with it later. Maybe I’ll write something up for you and post some code.)

(Actually, now that I think about the above a bit, it might make the music sound really weird (outside of the obvious effect)… hmm. A thought, using audio to create art, only using audio as the brush… hmm…)

0
167 Mar 01, 2007 at 23:37

frank, sounds to me like you need to read the OpenAL documentation more thoroughly. I found this in just a few minutes of searching:

AL_SEC_OFFSET Description: the playback position, expressed in seconds (the value will loop back to zero for looping sources).
AL_SAMPLE_OFFSET Description: the playback position, expressed in samples (the value will loop back to zero for looping sources).
AL_PITCH Description: Desired pitch shift, where 1.0 equals identity. Each reduction by 50 percent equals a pitch shift of -12 semitones (one octave reduction). Each doubling equals a pitch shift of 12 semitones (one octave increase).

These are all OpenAL source states you can set with the alSource functions.

0
101 Mar 02, 2007 at 10:56

Where can I find the array where the wavdata is loaded into?
Changing the actual data (ALvoid* data) is not possible in this way:
&data[0] = &data[1];

0
101 Mar 02, 2007 at 12:56

Here is how I do it…

A buffer…

ALbyte mybuf[BUF_SIZE];


Which you capture samples too…

alcGetIntegerv(mydevice, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &samples);
alcCaptureSamples(mydevice, (ALCvoid *)mybuf, samples);


And put them in this vector called cvals as I did…

for (i=0; i<samplesize; i++)
{
bval = (ALint)((ALint *)mybuf)[i];
cvals.push_back( bval );
}


Then you do what ever you want….

0
101 Mar 02, 2007 at 13:33

Figured I need to write my own .wav loader. Everything seems to have gone successfull. However, it crashed when generating sources.

#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream.h>

#include <al/al.h>
#include <al/alc.h>
#include <al/alut.h>

int chunksize;
int audio_format;
int sizechunk;
int sub2chunksize;

ALenum format;
ALsizei size;
ALvoid* data;
ALsizei freq;
ALboolean loop;

/*
* These are OpenAL "names" (or "objects"). They store and id of a buffer
* or a source object. Generally you would expect to see the implementation
* use values that scale up from '1', but don't count on it. The spec does
* not make this mandatory (as it is OpenGL). The id's can easily be memory
* pointers as well. It will depend on the implementation.
*/

// Buffers to hold sound data.
ALuint Buffer;

// Sources are points of emitting sound.
ALuint Source;

/*
* These are 3D cartesian vector coordinates. A structure or class would be
* a more flexible of handling these, but for the sake of simplicity we will
* just leave it as is.
*/

// Position of the source sound.
ALfloat SourcePos[] = { 0.0, 0.0, 0.0 };

// Velocity of the source sound.
ALfloat SourceVel[] = { 0.0, 0.0, 0.0 };

// Position of the Listener.
ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };

// Velocity of the Listener.
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };

// Orientation of the Listener. (first 3 elements are "at", second 3 are "up")
// Also note that these should be units of '1'.
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0,  0.0, 1.0, 0.0 };

{
FILE* file = fopen("C:/wavdata/FancyPants.wav","r+");
char* c;
char buffer[40000];

if (file)
{

/* Now get the wav data! */

if (strcmp(c,"RIFF"))
{
printf("RIFF\n");
} else {
printf("NO RIFF?!\n");
}

chunksize = atoi(c);
fread(c,1,4,file);      /* should contain WAVE */
cout << c << "\n";

/* SUBCHUNK */
cout << c << "\n";
sizechunk = atoi(c);
if (sizechunk != 16)
cout << c << "Not 16?\n";

audio_format = atoi(c); /* Suppose it's PCM, for now */
fread(c,1,2,file);      /* Bits per sample */

while (c[0] != 'd')
{
}
/* Dirty, but go to the Subchunk2ID */

printf("Copying buffer\n");
/* now get the data */

memcpy(&data,&buffer,10000);

fclose(file);

} else {
printf("Error opening WAVE");
}
system("PAUSE");
}

/*
*
*  This function will load our sample data from the disk using the Alut
*  utility and send the data into OpenAL as a buffer. A source is then
*  also created to play that buffer.
*/
{

// Load wav data into a buffer.

alGenBuffers(1, &Buffer);

if(alGetError() != AL_NO_ERROR)
return AL_FALSE;

//alutLoadWAVFile("wavdata/FancyPants.wav", &format, &data, &size, &freq, &loop);

system("PAUSE");
alBufferData(Buffer, format, data, size, freq);
system("PAUSE");
// Bind the buffer with the source.

alGenSources(1, &Source);
if(alGetError() != AL_NO_ERROR)
return AL_FALSE;
printf("Sources generated\n");
system("PAUSE");

alSourcei (Source, AL_BUFFER,   Buffer   );
alSourcef (Source, AL_PITCH,    1.0      );
alSourcef (Source, AL_GAIN,     1.0      );
alSourcefv(Source, AL_POSITION, SourcePos);
alSourcefv(Source, AL_VELOCITY, SourceVel);
alSourcei (Source, AL_LOOPING,  loop     );

printf("Sources set\n");
system("PAUSE");

// Do another error check and return.

if(alGetError() == AL_NO_ERROR)
return AL_TRUE;

return AL_FALSE;
}

/*
* void SetListenerValues()
*
*  We already defined certain values for the Listener, but we need
*  to tell OpenAL to use that data. This function does just that.
*/
void SetListenerValues()
{
alListenerfv(AL_POSITION,    ListenerPos);
alListenerfv(AL_VELOCITY,    ListenerVel);
alListenerfv(AL_ORIENTATION, ListenerOri);
}

/*
* void KillALData()
*
*  We have allocated memory for our buffers and sources which needs
*  to be returned to the system. This function frees that memory.
*/
void KillALData()
{
alDeleteBuffers(1, &Buffer);
alDeleteSources(1, &Source);
alutExit();
}

int main(int argc, char *argv[])
{

// Initialize OpenAL and clear the error bit.

alutInit(NULL, 0);
alGetError();

{
return 0;
}

printf("MindCode's OpenAL Lesson 1: Single Static Source\n\n");
printf("Controls:\n");
printf("p) Play\n");
printf("s) Stop\n");
printf("h) Hold (pause)\n");
printf("q) Quit\n\n");

SetListenerValues();

// Setup an exit procedure.

atexit(KillALData);

// Loop.

ALubyte c = ' ';

while(c != 'q')
{
c = getche();

switch(c)
{
// Pressing 'p' will begin playing the sample.

case 'p': alSourcePlay(Source); break;

// Pressing 's' will stop the sample from playing.

case 's': alSourceStop(Source); break;

// Pressing 'h' will pause the sample.

case 'h': alSourcePause(Source); break;
};

}

return 0;
}

0
101 Mar 18, 2007 at 23:55

Firstly, setting AL_PITCH changes the speed (and as a direct result the pitch) of your sound, so if you don’t care about high sounding voices, etc just use that. Secondly, if you do care about that (i.e. you don’t want the pitch to change), then just doubling samples won’t work, you’ll have to double sets of two sequential samples then (if my mathematics are correct here when applied to sound). Thirdly, does you’re code really crash at alGenSources? You might want to use a debugger there, because that seems a strange call to crash at (assuming your passed pointer to alGenSources is correct and doesn’t raise a segfault).