Get part of a source / buffer

View: New views
8 Messages — Rating Filter:   Alert me  

Get part of a source / buffer

by Niall09 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

Is there any way to get a part of a buffer that im playing, as i want to take a tiny part of the currently playing buffer, convert it to a short and put it through pitch detection. So i can detect the pitch dynamically as a sound plays.

Thanks,

Niall.

Re: Get part of a source / buffer

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sunday 24 May 2009 6:15:37 am Niall09 wrote:
> Hi,
>
> Is there any way to get a part of a buffer that im playing, as i want to
> take a tiny part of the currently playing buffer, convert it to a short and
> put it through pitch detection. So i can detect the pitch dynamically as a
> sound plays.

Hi.

You can't get the current buffer data OpenAL is playing, but you can get the
current position in the buffer. With the position, you can reference your own
copy of the data for pitch detection. As an example:

ALshort *data;
ALuint frames;
ALuint channels;
ALuint freq;
...

alBufferData(buffer, ((channels==1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16),
             data, frames*channels*2, freq);
alSourcei(source, AL_BUFFER, buffer);
...

ALfloat pos;
alGetSourcef(source, AL_SEC_OFFSET, &pos);

detect_pitch(&data[(ALuint)(pos*freq) * channels]);


That is, of course, assuming 16-bit data. Easy enough to modify for 8- or 32-
bit, though.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Get part of a source / buffer

by Niall09 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I keep trying your example, but &data[(ALuint)(pos*freq) * channels] keeps returning 0.

Chris Robinson-5 wrote:
On Sunday 24 May 2009 6:15:37 am Niall09 wrote:
> Hi,
>
> Is there any way to get a part of a buffer that im playing, as i want to
> take a tiny part of the currently playing buffer, convert it to a short and
> put it through pitch detection. So i can detect the pitch dynamically as a
> sound plays.

Hi.

You can't get the current buffer data OpenAL is playing, but you can get the
current position in the buffer. With the position, you can reference your own
copy of the data for pitch detection. As an example:

ALshort *data;
ALuint frames;
ALuint channels;
ALuint freq;
...

alBufferData(buffer, ((channels==1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16),
             data, frames*channels*2, freq);
alSourcei(source, AL_BUFFER, buffer);
...

ALfloat pos;
alGetSourcef(source, AL_SEC_OFFSET, &pos);

detect_pitch(&data[(ALuint)(pos*freq) * channels]);


That is, of course, assuming 16-bit data. Easy enough to modify for 8- or 32-
bit, though.
_______________________________________________
Openal-devel mailing list
Openal-devel@opensource.creative.com
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Get part of a source / buffer

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Monday 25 May 2009 6:53:41 am Niall09 wrote:
> Hi,
>
> I keep trying your example, but &data[(ALuint)(pos*freq) * channels] keeps
> returning 0.

You need to set the variables to the proper values.. data points to the PCM
sound data you want to play, frames is the number of frames (number of samples
divided by the number of channels; note that OpenAL's use of 'sample' actually
means 'frame'), channels is the number of channels, and freq is the sample
rate.

If those values are correct and you meant
(ALuint)(pos*freq) * channels
keeps giving 0, that should only happen if pos is 0.0, meaning the source
isn't playing.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Get part of a source / buffer

by Niall09 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson-5 wrote:
You need to set the variables to the proper values.. data points to the PCM
sound data you want to play, frames is the number of frames (number of samples
divided by the number of channels; note that OpenAL's use of 'sample' actually
means 'frame'), channels is the number of channels, and freq is the sample
rate.

If those values are correct and you meant
(ALuint)(pos*freq) * channels
keeps giving 0, that should only happen if pos is 0.0, meaning the source
isn't playing.
Im trying alBufferData(buffer, AL_FORMAT_STEREO16,data,frames*channels*2, freq) but when i run it, i get a error:

malloc: *** mmap(size=3143925760) failed (error code=12)
*** error: can't allocate region

and when i debug it, by making it output the frames*channels and frames*channels*2 to the console, frames*channels is 1571962880 (frames is 5292032 and channels is 4355) and frames*channels*2 is -1151041536.


Re: Get part of a source / buffer

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Monday 25 May 2009 9:53:24 am Niall09 wrote:
> Im trying alBufferData(buffer, AL_FORMAT_STEREO16,data,frames*channels*2,
> freq) but when i run it, i get a error:
>
> malloc: *** mmap(size=3143925760) failed (error code=12)
> *** error: can't allocate region
>
> and when i debug it, by making it output the frames*channels and
> frames*channels*2 to the console, frames*channels is 1571962880 (frames is
> 5292032 and channels is 4355) and frames*channels*2 is -1151041536.

How are you setting the frames/channels/freq/data variables?
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel

Re: Get part of a source / buffer

by Niall09 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Chris Robinson-5 wrote:
How are you setting the frames/channels/freq/data variables?
For the channels: channels = AL_FORMAT_STEREO16;

For the frames, freq and data: data = getOpenALAudioData(fileURL, &size3, &format3, &freq,&frames);

void* getOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALuint* outSampleRate,ALuint * frames)
{
        OSStatus err = noErr;
        SInt64 theFileLengthInFrames = 0;
        AudioStreamBasicDescription theFileFormat;
        UInt32 thePropertySize = sizeof(theFileFormat);
        printf("\nT: %i : %d \n",sizeof(theFileFormat),sizeof(theFileFormat));
        ExtAudioFileRef extRef = NULL;
        void* theData = NULL;
        AudioStreamBasicDescription theOutputFormat;
       
        // Open a file with ExtAudioFileOpen()
        err = ExtAudioFileOpenURL(inFileURL, &extRef);
        if(err) { printf("MyGetOpenALAudioData: ExtAudioFileOpenURL FAILED, Error = %ld\n", err); goto Exit; }
       
        // Get the audio data format
        err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &theFileFormat);
        if(err) { printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %ld\n", err); goto Exit; }
        if (theFileFormat.mChannelsPerFrame > 2)  { printf("MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n"); goto Exit;}
       
        // Set the client format to 16 bit signed integer (native-endian) data
        // Maintain the channel count and sample rate of the original source format
        theOutputFormat.mSampleRate = theFileFormat.mSampleRate;
        theOutputFormat.mChannelsPerFrame = theFileFormat.mChannelsPerFrame;
       
        theOutputFormat.mFormatID = kAudioFormatLinearPCM;
        theOutputFormat.mBytesPerPacket = 2 * theOutputFormat.mChannelsPerFrame;
        theOutputFormat.mFramesPerPacket = 1;
        theOutputFormat.mBytesPerFrame = 2 * theOutputFormat.mChannelsPerFrame;
        theOutputFormat.mBitsPerChannel = 16;
        theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
       
        // Set the desired client (output) data format
        err = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(theOutputFormat), &theOutputFormat);
        if(err) { printf("MyGetOpenALAudioData: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) FAILED, Error = %ld\n", err); goto Exit; }
       
        // Get the total frame count
        thePropertySize = sizeof(theFileLengthInFrames);
        //AL_SAMPLE
        err = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames);
        if(err) { printf("MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %ld\n", err); goto Exit; }
       
        // Read all the data into memory
        UInt32 dataSize = theFileLengthInFrames * theOutputFormat.mBytesPerFrame;
        theData = malloc(dataSize);
        *frames = theFileLengthInFrames;
        if (theData)
        {
                AudioBufferList theDataBuffer;
                theDataBuffer.mNumberBuffers = 1;
                theDataBuffer.mBuffers[0].mDataByteSize = dataSize;
                theDataBuffer.mBuffers[0].mNumberChannels = theOutputFormat.mChannelsPerFrame;
                theDataBuffer.mBuffers[0].mData = theData;
               
                // Read the data into an AudioBufferList
                err = ExtAudioFileRead(extRef, (UInt32*)&theFileLengthInFrames, &theDataBuffer);
                if(err == noErr)
                {
                        // success
                        *outDataSize = (ALsizei)dataSize;
                        *outDataFormat = (theOutputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
                        *outSampleRate = (ALsizei)theOutputFormat.mSampleRate;
                }
                else
                {
                        // failure
                        free (theData);
                        theData = NULL; // make sure to return NULL
                        printf("MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %ld\n", err); goto Exit;
                }
        }
       
Exit:
        // Dispose the ExtAudioFileRef, it is no longer needed
        if (extRef) ExtAudioFileDispose(extRef);
        return theData;
}

Re: Get part of a source / buffer

by Chris Robinson-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Monday 25 May 2009 10:33:25 am Niall09 wrote:
> For the channels: channels = AL_FORMAT_STEREO16;

That should be the number of channels (1 or 2, depending if the data's mono or
stereo), not an OpenAL enum. The enum itself uses a defined, but arbitrary,
value, and isn't useful for calculating the sample offset from the position.
_______________________________________________
Openal-devel mailing list
Openal-devel@...
http://opensource.creative.com/mailman/listinfo/openal-devel