Sign in to follow this  
enigmagame

Real-time sound processing

Recommended Posts

Hi! For a school project I must apply a filter to a sound. I use OpenGL for draw the sound emitter, and for example I can use OpenAL for the sound processing. Is possibile with OpenAL modify the sound data on real-time (with a my function)? Or I must use another api? Thanks!

Share this post


Link to post
Share on other sites
I suggest you SDL_Mixer. With SDL_Mixer you can register your own functions for edit the sound in realtime.
Example:

// make a passthru processor function that does nothing...
void noEffect(int chan, void *stream, int len, void *udata)
{
// you could work with stream here...
}
...
// register noEffect as a postmix processor
if(!Mix_RegisterEffect(MIX_CHANNEL_POST, noEffect, NULL, NULL))
{
printf("Mix_RegisterEffect: %s\n", Mix_GetError());
}



"noEffect" is your function that will be called everytime before the sound be played. *stream is the pointer to the sound data, there you can feed that pointer with your own data, or take the data for raw edit, or just get the actual sound data for make something like a digital vumeter, like those in programs like winamp.

Share this post


Link to post
Share on other sites
Ok, thanks.
But I'm new to SDL and SDL_Mixer, so I've some questions.
I've this code:

#include <stdio.h>
#include <SDL.h>
#include <SDL_Mixer.h>

void HeadShadowEffect(int chan, void* stream, int len, void* udata);

int main(int argc, char** argv)
{
SDL_Surface* screen;
int audio_rate = 44100;
Uint16 audio_format = AUDIO_S16SYS;
int audio_channels = 2;
int audio_buffers = 4096;
Mix_Chunk *sound = NULL;
int channel;

SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);

Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers);

sound = Mix_LoadWAV("ape.wav");

screen = SDL_SetVideoMode(1280, 800, 0, 0);

Mix_RegisterEffect(MIX_CHANNEL_POST, HeadShadowEffect, NULL, NULL);

channel = Mix_PlayChannel(-1, sound, 0);

while(Mix_Playing(channel) != 0);

Mix_FreeChunk(sound);
Mix_CloseAudio();
SDL_Quit();

return 1;
}

void HeadShadowEffect(int chan, void* stream, int len, void* udata)
{
}


A wav file is loaded and played for one time and "HeadShadowEffect" is a function registred as Mix_RegisterEffect().
Now in this function, I can modify my audio data, but how? For example if I want multiply each data for a constant value, how I can do this?
Thanks.

Share this post


Link to post
Share on other sites
Quote:
Original post by enigmagame
Ok, thanks.
But I'm new to SDL and SDL_Mixer, so I've some questions.
I've this code:
*** Source Snippet Removed ***
A wav file is loaded and played for one time and "HeadShadowEffect" is a function registred as Mix_RegisterEffect().
Now in this function, I can modify my audio data, but how? For example if I want multiply each data for a constant value, how I can do this?
Thanks.


In your code, you open initialize SDL_mixer with 2 channels and signed 16 bit audio format. This is very important to know, because that will be the format of the stream pointer in your function callback.

The data that comes in stream is pointer of size len bytes, but your data is 16 bit (2 bytes), then cast to a short pointer, and the size will be len/2.
Example:

void HeadShadowEffect(int chan, void* stream, int len, void* udata)
{
short* p = (short*) stream;
/* size= len/2 beause we use 2 bytes values, len is the size of stream in bytes */
int length = len/2;
}






Since you initialized with 2 channels (stereo), given i a positive number multiple of 2 (0,2,4,6,8,10,...), then p[i] is the sound data for left channel, and p[i+1] is data for right channel.

Now, for example, you wanted to multiply the sound data for a constant value.
We do something like this:

void HeadShadowEffect(int chan, void* stream, int len, void* udata)
{
float value=1.5f;
short* p = (short*) stream;
int length = len/2;

/* Iterate over p 2 by 2 */
for (int i=0; i<length/2;i++)
{
p[i*2]=0;
p[i*2+1]=(short)(p[i*2+1]*value);
}
}





In this example, we mute the left channel, and multiply the sound data of the right channel by 1.5 (this increases volume of right channel).
Multiply the channels by a value causes increase or decrease volume.

SDL_mixer is fun to test, you can produce some sound efects with code, or as I said, you can get the sound data, and render something with the music, like those winap plugins that shows patterns according with the music that you play

Hope that helps!

And sorry for my bad english, its hard to explain stuff in a language that I'm still learning :)

Share this post


Link to post
Share on other sites
Quote:
Original post by martin_bfg10k
Hope that helps!

And sorry for my bad english, its hard to explain stuff in a language that I'm still learning :)

No, it's clear and thanks for help!
I've tried this code, it's runs, and I've understand how to stream works. But I'm not sure if this function is suitable for my filter. In our simple example, we've multiplied a channel for a costant value, and we've set to zero the other channel.
In my filter I must implement two blocks, and one of this blocks is a delay line, the two channel are delayed with different value.
If I work in a "no real-time" situation, I proceed in this manner:
- delay[0] is the delay for the left channel
- delay[1] is the delay for the right channel
1) wav file reading
2) data of left channel are shifted of delay[0] value and then I add his original value, data of right channel are shifted of delay[1] value and then I add his original value.
Note that I don't delete the original value, but I shift that.
3) save the data to another wav file and play.
In this "no real-time mode", it's runs, and I obtain, the searched delay.
But for my project, I must modify the delay value, and the results must be in real-time.
For your experience, is possibile to do this with SDL_Mixer and with this function?
Thanks very much!

Share this post


Link to post
Share on other sites
For example, I must implement something like this:

void HeadShadowEffect(int chan, void* stream, int len, void* udata)
{
short* p = (short*) stream;
int length = len/2;

//Delay for the left channel
delay[0] = delay[0] * 44100; \\28 values
//Delay for the right channel
delay[1] = delay[1] * 44100; \\1 values

for(int i = 0; i < length/2; i++)
{
//Shift left channel of delay[0] values
if(i < delay[0])
{
}

//Shift right channel of delay[0] values
if(i < delay[1])
{
}
}
}


I don't understand if is possible implement that, and how.
Thanks.

Share this post


Link to post
Share on other sites
Hi,
I've tried to implement the delay line with this code:

void hrtf(int chan, void* stream, int len, void* udata)
{
short* audioData = (short*) stream;
int audioLength = len / 2;

delay[0] = 28;
delay[1] = 1;

for(int i = 0; i < (audioLength / 2); i++)
{
audioTemp[i*2] = audioData[i*2];
audioTemp[i*2+1] = audioData[i*2+1];
}

for(int i = 0; i < (audioLength / 2); i++)
{
if(i < delay[0])
{
audioData[i*2] = 0;
}
else
{
audioData[i*2] = audioTemp[(i*2) - (int)delay[0]];
}

if(i < delay[1])
{
audioData[i*2+1] = 0;
}
else
{
audioData[i*2+1] = audioTemp[(i*2+1) - (int)delay[1]];
}
}
}


I would to shift the left channel of 28 values and right channel of 1 value.
The result is not the same that I obtained in a static version. For me is not
very correct and the audio of the channel major delayed (left channel) is disturbed.
Some suggestions?
Thanks.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this