OpenAL speed

Ab72642c356a964d69362d36d263be3d
0
frank 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)

Thanks in advance,
Frank

6 Replies

Please log in or register to post a reply.

1de588970b4171e14640a46a28f20032
0
threeam 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…)

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 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.

Ab72642c356a964d69362d36d263be3d
0
frank 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];

1de588970b4171e14640a46a28f20032
0
threeam 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….

Ab72642c356a964d69362d36d263be3d
0
frank 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;

// Variables to load into.
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 };


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

     /* Now get the wav data! */
     printf("WAVE file loaded\n");    
     
     /* RIFF HEADER */
     fread(c,1,4,file);
        
        if (strcmp(c,"RIFF"))
        {
         printf("RIFF\n");
        } else { 
         printf("NO RIFF?!\n");
        }            
                       
        fread(c,1,4,file);      /* chunk size*/
        chunksize = atoi(c);
        fread(c,1,4,file);      /* should contain WAVE */
        cout << c << "\n";
          
        /* SUBCHUNK */
        fread(c,1,4,file);      /* fmt .. */
        cout << c << "\n";
        fread(c,1,4,file);      /*  subchunk size */
        sizechunk = atoi(c);
        if (sizechunk != 16) 
        cout << c << "Not 16?\n";

        fread(c,1,2,file);      /* Compression code */
        audio_format = atoi(c); /* Suppose it's PCM, for now */
        fread(c,1,2,file);      /* Num channels */
        fread(c,1,4,file);      /* Sample rate */
        fread(c,1,4,file);      /* Byte rate */
        fread(c,1,2,file);      /* Block align */
        fread(c,1,2,file);      /* Bits per sample */      
 
        while (c[0] != 'd')
        {
         fread(c,1,1,file);      
        }
         /* Dirty, but go to the Subchunk2ID */
       
        fread(c,1,3,file);      
        fread(c,1,4,file);      /* Sub2chunksize */
        
        printf("Copying buffer\n");
        /* now get the data */
      

        fread(buffer,1,10000,file);
        memcpy(&data,&buffer,10000);
                           
     fclose(file);
 
    } else {
     printf("Error opening WAVE");       
    }        
    system("PAUSE");
}


/*
 * ALboolean LoadALData()
 *
 *  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.
 */
ALboolean LoadALData()
{


    // 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);

    loadwav();

    printf("\nWAV Loaded\n");
    system("PAUSE");
    alBufferData(Buffer, format, data, size, freq);
    //alutUnloadWAV(format, data, size, freq);
    printf("Loaded into buffer\n");
    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();

    // Load the wav data.

    if(LoadALData() == AL_FALSE)
    {
        printf("Error loading data.");
        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;
}
067cb9c7f98462ac5efcb25ea571f21b
0
MuggenHor 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).