1

I'm playing around with pa_simple api to get a better understanding of digital audio. I've written some code to feed custom generated audio data to the pulseaudio server:

char buff[2];
while (playing) {
    timePassed += periodMicros;
    int val = userFunc(timePassed/1000000.0);
    buff[0] = (val >> 0) & 0xff;
    buff[1] = (val >> 1) & 0xff;
    int error;
    pa_simple_write(s, buff, 2, &error);
}

func generates a simple sine wave like this:

uint16_t func(double time)
{   
    double op = sin(2*3.14*freq * time);
    return op * 100;
}

It produces a note as expected, but eats up 50% of cpu on my machine, because of the unrestricted while loop in the first codeblock. So I tried fixing it like this:

void _mainLoop() {
    char buff[2*bufSize];
    while (playing) {
        for ( int i = 0; i < bufSize; i++ ) {
            uint8_t word = userFunc(timePassed/1000000.0);
            timePassed += periodMicros;
            buff[i*2+0] = (word >> 0) & 0xff;
            buff[i*2+1] = (word >> 1) & 0xff;
        }
        pa_simple_write(s, buff, 2*bufSize, &error);
        this_thread::sleep_for(chrono::microseconds(bufSize*periodMicros));
    }
}

It fixes the cpu issue but the audio generated by it is no longer a perfect note. It appears to be a bit higher pitched with a retro feel to it.

I wanted to know the correct way to use the pa_simple api without my code eating up the cpu.

Note that the sound generated by second code isn't fixed even if I change bufSize to 1 and remove the sleep line.

Edit: This is how I've initialized the pulseaudio connection:

pa_sample_spec ss = {
    .format = PA_SAMPLE_S16LE,
    .channels = 1,
    .rate = 44100
};
s = pa_simple_new(
    NULL,
    "SYNTH",
    PA_STREAM_PLAYBACK,
    NULL,
    "Music",
    &ss,
    NULL,
    NULL,
    NULL
);

saga
  • 1,933
  • 2
  • 17
  • 44

1 Answers1

1

It was a bug in the program. I was storing the output of userFunc in a uint, hence the negative values were being cutoff. Changing that to int and removing the sleep call fixed the problem, since the pa_simple api in synchronous.

saga
  • 1,933
  • 2
  • 17
  • 44