Why does this click?

Hiya,

I’ve used SDL audio in the past, and not had problems, but I’ve been staring
at this code for hours, and can’t work out why on earth it’s clicking! It
should just play a sine wave. My machine is a dual core P4, so I doubt it’s
a CPU issue. Anyone who spots the probably obvious mistake, please yell
loudly at me :-)-

#include <SDL/SDL.h>
#include <SDL/SDL_audio.h>
#include
#include <math.h>
#include <sys/types.h>

using std::cout;
using std::endl;

SDL_AudioSpec fmt;
float sine_pos;
float sine_speed;

const int channels = 1;
const int audio_freq = 44100;
const int step_size = 8192;
const int note_freq = 440; // (440 hz = middle A)

int16_t mixbuf[step_size];

void mix(void* data, Uint8* stream, int len)
{
for (int i=0; i<step_size; i++) {
mixbuf[i] = (int16_t) (16000.0f * __builtin_sinf(sine_pos));
sine_pos += sine_speed;
}

SDL_MixAudio(stream, (Uint8*) mixbuf, len, SDL_MIX_MAXVOLUME);

}

void init()
{
fmt.freq = audio_freq;
fmt.format = AUDIO_S16SYS;
fmt.channels = channels;
fmt.samples = step_size;
fmt.callback = mix;
fmt.userdata = NULL;

if (SDL_OpenAudio(&fmt, NULL) < 0) {
cout << "Failed to open audio: " << SDL_GetError() << endl;
exit(1);
}

sine_pos = 0;
sine_speed = M_PI * 2 * note_freq / audio_freq;

}

int main(int argc, char* argv[])
{
init();
SDL_PauseAudio(0);
sleep(10);
SDL_PauseAudio(1);
}

Hello Giles,

Tuesday, February 28, 2006, 7:46:19 PM, you wrote:

GC> Hiya,

GC> I’ve used SDL audio in the past, and not had problems, but I’ve been staring
GC> at this code for hours, and can’t work out why on earth it’s clicking! It
GC> should just play a sine wave. My machine is a dual core P4, so I doubt it’s
GC> a CPU issue. Anyone who spots the probably obvious mistake, please yell
GC> loudly at me :slight_smile:

Why are you calling SDL_MixAudio() ?

In the mix callback, you should fully fill whatever buffer you’re
given, in other words, fill stream with up to len samples. If you
don’t, you’ll be sending blank data to the card to play.–
Best regards,
Peter mailto:@Peter_Mulholland

Ok… changed to this. still skips :-/ :

void mix(void* data, Uint8* stream, int len)
{

for (int i=0; i < (len / (channels*sizeof(int16_t))) ; i++) 
{
    mixbuf[i] = (int16_t) (16000.0f * __builtin_sinf(sine_pos));
    sine_pos += sine_speed;
}

memcpy(stream, mixbuf, len);

}On Tuesday 28 February 2006 20:08, Peter Mulholland wrote:

Why are you calling SDL_MixAudio() ?

In the mix callback, you should fully fill whatever buffer you’re
given, in other words, fill stream with up to len samples. If you
don’t, you’ll be sending blank data to the card to play.

Hello Giles,

Tuesday, February 28, 2006, 9:09:07 PM, you wrote:

GC> Ok… changed to this. still skips :-/ :

step_size could change after the call to SDL_OpenAudio(). You
should be checking what was actually obtained from this call.

Also, for this simple sine wave generator, why use an intermediate
buffer instead of just rendering straight into the buffer passed to
the mix callback?

You also want to check you’re generating data that is the right
signedness.–
Best regards,
Peter mailto:@Peter_Mulholland

GC> Ok… changed to this. still skips :-/ :

step_size could change after the call to SDL_OpenAudio().

It didn’t… and i’m not referencing it in the mix function.

You should be checking what was actually obtained from this call.

When I pass a pointer to an “obtained” SDL_AudioSpec, it comes out pretty much
identical to what was requested.

Also, for this simple sine wave generator, why use an intermediate
buffer instead of just rendering straight into the buffer passed to
the mix callback?

The code I’ve published to this list is a much simplified version of a much
larger program I’m writing which involves drawing data from a chain of
generators, which generate 64 samples per function call - I’m having to
buffer it in this way for an unavoidable reason. The code I wrote to the
list was just a small program I wrote to emulate the problem.

You also want to check you’re generating data that is the right
signedness.

I printf’d the output and piped it through xgraph, and it appeared to be
correct. It corresponds to the “silence” value produced in the obtained
SDL_AudioSpec.

cheers,

GilesOn Tuesday 28 February 2006 21:54, Peter Mulholland wrote: