Jump to content
  • Advertisement
Sign in to follow this  
ratalert

sdl_audio: play five tones with exact duration

This topic is 3399 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys, I'm very new in programming with sdl and now I got a question. I'd like to play 5 tones of different frequencies (2000 - 2600 - 2400 - 1160 - 2600 Hz) each with an exact duration of 70ms. Currently my callback function that produces a tone looks like this: void play_tones(void* userdata, Uint8* stream, int len) { int i; int num_samples = len / 2; static int pos = 0; float buffer[BUFFER_SIZE]; Sint16 *dst_buf = (Sint16*) stream; for (i=0; i<num_samples ; ++i) buffer = sin(1160.0f*(i+pos)/(float)SAMPLING_RATE); // Clipping and conversion to Sint16 for (i=0; i<num_samples; ++i) { float v = buffer; if (v > 1.0f) v = 1.0f; else if (v< -1.0f) v = -1.0f; dst_buf = (Sint16)(32767.0f*v); } pos += num_samples; } BUFFER_SIZE is 1024 SAMPLING_RATE is 44100 I hope anybody can help me with that. Thanks a lot in advance. ratalert

Share this post


Link to post
Share on other sites
Advertisement
Well. If I would do that, then I would pre-record these tones, then load them and play them. But it is heavy to get those tones probably. So sorry I don't got a good idea.

Share this post


Link to post
Share on other sites
I can't record them before playing because the combination of tones in a serie differs every time.

for example once I'd like to play
2000 - 2600 - 2400 - 1160 - 2600 Hz
Next time
2200 - 1270 - 2400 - 1270 - 2600 Hz

The only thing which is not changing is every time five tones with a duration of 70ms.

Is there really no way?

Share this post


Link to post
Share on other sites
I'm not familiar with sdl_audio... but isn't there sdl_mixer?

I think you need to precompute your five buffers, and if sdl_mixer lives up to its name and has a sane interface, there should be no problem with it mixing five buffers at once in real time. I imagine you'd choose whatever 5 buffers it is this time around, and tell sdl_mixer to play them, and it'd mix them and play them all at once. And it appears I imagine correctly, if the docs are to be believed:

http://jcatki.no-ip.org:8080/SDL_mixer/SDL_mixer_frame.html

if your buffers are precomputed and called
buf1, buf2, buf3, buf4, buf5, and you randomly (or however) select 5 of them (with possible duplicates) into b1, b2, b3, b4, b5, then to play them, wouldn't you just do this?


Mix_PlayChannel(-1, b1, 1);
Mix_PlayChannel(-1, b2, 1);
Mix_PlayChannel(-1, b3, 1);
Mix_PlayChannel(-1, b4, 1);
Mix_PlayChannel(-1, b5, 1);





Share this post


Link to post
Share on other sites
alright, sounds good.

due to that I need to define 5 buffer with a tone in a particular frequency and play that first buffer 70ms, then I play the second buffer for the same time.

Is that possible with sdl_mixer?

Share this post


Link to post
Share on other sites
Quote:
Original post by ratalert
I hope anybody can help me with that. Thanks a lot in advance.

What is the actual problem you're having?

I would solve the problem this way:
- create a buffer big enough to hold your 5 tones (eg. 350ms, ie. an array pf 15435 Sint16s)
- generate each tone and fill this buffer with them, one after the other
- make your callback read a bit from that buffer each time

You don't need SDL_Mixer or any other kind of mixing for that.

Share this post


Link to post
Share on other sites
Kylotan, this is exactly what I want to do.
This is what I tried, it's not really correct I think - can you just please tell me what I'm doing wrong?

void play_tones(void* userdata, Uint8* stream, int len)
{
int size = 15435;
float buffer[15435];

Sint16 *dst_buf = (Sint16*) stream;
for (i=0; i<size/5 ; i++)
buffer = sin(2000.0f /(float)SAMPLING_RATE);
for (int x=i; x<size/5 ; x++)
buffer[x] = sin(2600 .0f /(float)SAMPLING_RATE);
for (int z=x; z<size/5 ; z++)
buffer[z] = sin(2400.0f /(float)SAMPLING_RATE);
for (int l=z; l<size/5 ; l++)
buffer[l] = sin(1160.0f /(float)SAMPLING_RATE);
for (int n=l; n<size/5 ; n++)
buffer[n] = sin(2600.0f /(float)SAMPLING_RATE);
}

int main()
{
SDL_Init(SDL_INIT_AUDIO);


audio.channels = 1; // Stereo = 2; Mono = 1
audio.format = AUDIO_S16; // Format
audio.freq = 44100; // 44 kHz
audio.samples = 1024; // 1024 Samples (PCM)
audio.callback = play_tones; // Callback function

if(SDL_OpenAudio(&audio, NULL) < 0)
return 1;

SDL_PauseAudio(0);
}

Share this post


Link to post
Share on other sites
You're not giving the sin() function a meaningful input so the value is constant. Something like this will work better (PI is, of course, 3.14159 and then some...):

buffer = sin( i * 2000.0f * 2 * PI /(float)SAMPLING_RATE);

Share this post


Link to post
Share on other sites
you're right. I changed it. The programm is running but I just get a continious tone not like the five tones I was expecting...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!