sdl_audio: play five tones with exact duration

Started by
16 comments, last by ratalert 15 years, 2 months ago
Try showing the complete, current code? And put it in a [source][/source] box instead of code tags maybe?
Advertisement
alright, thanks I did not know about these tags

#include "cplayer.h"void play_tones(void*, Uint8*, int);#define PI 3.14159CPlayer::CPlayer(){    Init();}CPlayer::~CPlayer(){}void CPlayer::Init(){    m_desired.freq     = SAMPLING_RATE;    m_desired.format   = AUDIO_S16SYS;    //audio.format = AUDIO_S16; // Format    m_desired.channels = 1;    m_desired.samples  = BUFFER_SIZE;    m_desired.callback = play_tones;    m_desired.userdata = NULL;}bool CPlayer::Do(){    if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {        //fprintf(stderr, "SDL konnte nicht initialisiert werden: %s\n", SDL_GetError());        return false;    }    if ( SDL_OpenAudio(&m_desired, NULL) < 0 ) {        //fprintf(stderr, "SDL konnte nicht geoeffnet werden: %s\n", SDL_GetError());        return false;    }    SDL_PauseAudio(0);    getchar();    SDL_PauseAudio(1);    SDL_CloseAudio();    SDL_Quit();    return true;}void play_tones(void* userdata, Uint8* stream, int len){      int i;    int num_samples = len / 2;    static int pos = 0;    int size = 15435;    float buffer[15435];    int x, z,l,n;    Sint16 *dst_buf = (Sint16*) stream;    for (i=0; i<size/5 ; i++)        buffer = sin( i * 2000.0f * 2 * PI /(float)SAMPLING_RATE);    for (x=i; x<size/5 ; x++)        buffer[x] = sin( i * 2600.0f * 2 * PI /(float)SAMPLING_RATE);    for (z=x; z<size/5 ; z++)        buffer[z] = sin( i * 2400.0f * 2 * PI /(float)SAMPLING_RATE);    for (l=z; l<size/5 ; l++)        buffer[l] = sin( i * 1600.0f * 2 * PI /(float)SAMPLING_RATE);    for (n=l; n<size/5 ; n++)        buffer[n] = sin( i * 2600.0f * 2 * PI /(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;}
You're using the variable "i" for all tones. I'm surprised that's even generating 350ms worth of sound, and not just 70ms, since "i" is constant after the first tone is generated.
oh f***, damn copy & paste. thanks a lot ;)

nevertheless it produces just one raspy tone...

    int x, z,l,n;    Sint16 *dst_buf = (Sint16*) stream;    for (i=0; i<size/5 ; i++)        buffer = sin( i * 2000.0f * 2 * PI /(float)SAMPLING_RATE);    for (x=i; x<size/5 ; x++)        buffer[x] = sin( x * 2600.0f * 2 * PI /(float)SAMPLING_RATE);    for (z=x; z<size/5 ; z++)        buffer[z] = sin( z * 2400.0f * 2 * PI /(float)SAMPLING_RATE);    for (l=z; l<size/5 ; l++)        buffer[l] = sin( l * 1600.0f * 2 * PI /(float)SAMPLING_RATE);    for (n=l; n<size/5 ; n++)        buffer[n] = sin( n * 2600.0f * 2 * PI /(float)SAMPLING_RATE);


I think I might see the problem.

You've specified an audio format of:

audio.format = AUDIO_S16; // Format

Which is to say, you've told it that the data will be in signed 16 bit little endian integers.

But, the buffer you're filling out is full of floats instead:

float buffer[BUFFER_SIZE];

Instead, you want:

int16_t buffer[BUFFER_SIZE];

It needs to be a buffer full of signed 16 bit little endian ints. (include inttypes.h or stdint.h and use int16_t, or, on most intel hardware a "signed short" will work too, but is slightly less portable.)

That would explain the raspy sound... floating point format data interpreted as signed shorts would look (and sound) like garbage, as I'm sure you noticed. :)

These lines of code:

buffer = sin(1160.0f*(i+pos)/(float)SAMPLING_RATE);


Should probably be something like:

buffer = (int16_t) (32767.0f * (sin(1160.0f*(i+pos)/(float)SAMPLING_RATE)));

(In my previous reply I had thought you were trying to get the 5 tones played simultaneously, mixed together, for a grand total of 70ms worth of sound -- now I realize that's not what you were asking. Sorry about that.)
thanks a lot for the reply.

The tone I'm getting now doesn't sound raspy anymore but it's still just one continous tone.

void play_tones(void* userdata, Uint8* stream, int len){      int i;    int num_samples = len / 2;    static int pos = 0;    int size = 15435;    //float buffer[15435];    int16_t buffer[15435];    int x, z,l,n;    for (i=0; i<size/5 ; i++)         buffer = (int16_t) (32767.0f * (sin(2000.0f*(i+pos)/(float)SAMPLING_RATE)));    for (x=i; x<size/5 ; x++)        buffer[x] = (int16_t) (32767.0f * (sin(2600.0f*(i+pos)/(float)SAMPLING_RATE)));    for (z=x; z<size/5 ; z++)        buffer[z] = (int16_t) (32767.0f * (sin(2400.0f*(i+pos)/(float)SAMPLING_RATE)));    for (l=z; l<size/5 ; l++)        buffer[l] = (int16_t) (32767.0f * (sin(1600.0f*(i+pos)/(float)SAMPLING_RATE)));    for (n=l; n<size/5 ; n++)        buffer[n] = (int16_t) (32767.0f * (sin(2600.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;}
Uhhhhhh. Hmmmm.

I hadn't noticed that you had *another loop* that transformed the computed buffer full of floats into *another *(!!!!!) buffer full of signed 16 bit ints...

Uh, why compute the floats into a buffer only to transform the entire buffer to int16_t's?

And... given that you do that (which I hadn't previously noticed) why would computing the buffer of int16_t's directly, as I suggest, make a difference...

At this point, I give up.

Your code is buggy.

Advice: Debug it.
alright, thaanks for your help. I'll try debugging it as good as possible...

This topic is closed to new replies.

Advertisement