Why does sound play in an infinite loop only with delays inserted?

I’ve been writing some test code based off some examples I’ve found,
trying to understand how audio works under SDL.

The code I’ve written stays in an infinite loop after doing all the
initialization. I’ve found that I don’t hear any sound from my code,
unless I insert some delay in the infinite loop, and I was wondering if
someone could help me understand why this happens, either by explaining
it to me, or pointing me to some references that will do so (I’ve not
been able to find much to help). It may just be something to do with my
implementation.

The code itself is pasted below for reference. It writes a square wave
to a buffer, which is copied to the audio stream in the audio callback
function. In the infinite loop, there is a check to see if the buffer
contains less than 2048 bytes - if so, it calls another function to add
bytes to the buffer. The part that makes a difference is commenting out
"SDL_Delay(1)" - doing so gives no sound output except a short bit at
the beginning, not doing so makes the sound play fine. Another thing to
note is that when the delay is absent, although I can see that
sound_buf_nbytes is less than 2048 (0, actually) when the callback is
called (by uncommenting the printf within it), I only see “add some
bytes” printed a few times (7 times) at the beginning - even though it
should be meet the condition being checked for.

Thanks for any help.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include “SDL.h”

/* global variables to feed sound buffer with in callback */
Uint16 sound_buf_size;
Uint16 sound_buf_pos;
Uint16 sound_buf_nbytes;
Sint16 *sound_buf;

void fill_sound_buf(void)
{
int i;
int toggle = 0;

 SDL_LockAudio();
 for (i=0; i < 256; i++) {
     if (!(i % 100)) {
         toggle = ~toggle;
     }


     if (toggle) {
         sound_buf[sound_buf_pos+i] = 4096;
     }
     else {
         sound_buf[sound_buf_pos+i] = -4096;
     }

     if (sound_buf_pos >= (sound_buf_size>>1)) {
         sound_buf_pos = (sound_buf_size>>1) - 1;
     }
     sound_buf_nbytes++;
 }
 SDL_UnlockAudio();

 return;

}

/* sets up the above global sound variables */
void initialize_audio_vars(Uint8 *snd_buffer)
{
sound_buf = (Sint16 *)snd_buffer;
sound_buf_size = 2048;
sound_buf_pos = 0;
sound_buf_nbytes = 0;

 return;

}

/* sound callback function */
void test_call_back(void *userdata, Uint8 *stream, int len)
{
Sint16 *sound_data = (Sint16 *)stream;
len >>=1;

// printf(“len:%u nbytes:%u pos:%u\n”, len, sound_buf_nbytes,
sound_buf_pos);
while (len) {
if (sound_buf_nbytes) {
*sound_data = sound_buf[sound_buf_pos];
sound_buf_pos = (sound_buf_pos + 1) % (sound_buf_size>>1);
sound_buf_nbytes–;
}
else {
*sound_data = 0;
}
sound_data++;
len–;
}

 return;

}

int main(void)
{
int i;
Uint8 test_buf[4096] = {0};
SDL_AudioSpec desired;
SDL_AudioSpec obtained;

 /* begin initialization stuff */
 if (SDL_Init(SDL_INIT_AUDIO) == -1) {
     fprintf(stderr, "Can't initialize. SDL error: %s\n", 

SDL_GetError());
exit(EXIT_FAILURE);
}
else
{
printf(“Initialized SDL\n”);
}
atexit(SDL_Quit);

 desired.freq = 44100;
 desired.format = AUDIO_S16SYS;
 desired.channels = 1;
 desired.silence = 0;
 desired.samples = 512;
 desired.padding = 0;
 desired.size = 0;
 desired.callback = &test_call_back;
 desired.userdata = 0;

 if (SDL_OpenAudio(&desired, &obtained) < 0) {
     fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
 }
 else {
     printf("Opened Audio\n");
 }

 initialize_audio_vars(test_buf);
 printf("Initialized variables\n");


 fill_sound_buf();
 fill_sound_buf();

 printf("Filled sound buffer\n");
 printf("size:%u pos:%u nbytes:%u\n", sound_buf_size, sound_buf_pos, 

sound_buf_nbytes);

 SDL_PauseAudio(0);
 while (1) {
     SDL_Delay(1);
     if (sound_buf_nbytes <= 2048) {
         printf("add some bytes\n");
         fill_sound_buf();
     }

 }
 exit(EXIT_SUCCESS);

}–
J. A. McMahan Jr.