Playing sound in real-time based on a series of pulses

37 Views Asked by At

I have a black-box that emits signals (say calls a function) at unknown and varying intervals. Each emitted signal marks half a period in a square wave. The goal would be to produce the sound of said square wave.

My original idea was to open a portaudio stream and every time the signal is emitted play a short square wave, then silence. My assumption was that if the signal is emitted 400 times a second then this would result in a 200hz square wave.

Instead on my windows machine I hear a pop then nothing, definitely not what I know a 200hz square wave to be, inside a virtualbox ubuntu installation sometimes I also receive underrun occured errors.

#include <stdio.h>
#include <stdlib.h>
#include <portaudio.h>
#include <time.h>
#include <math.h>

void e(PaError err)
{
    if (err != paNoError)
    {
        Pa_Terminate();
        fprintf(stderr, "An error occurred while using the portaudio stream\n");
        fprintf(stderr, "Error number: %d\n", err);
        fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
    }
}

typedef struct
{
    int play;
} paData;

PaStreamParameters outputParameters;
static PaStream *stream;
static paData data;
static int count;

static int paCallback(const void *inputBuffer, void *outputBuffer,
                      unsigned long framesPerBuffer,
                      const PaStreamCallbackTimeInfo *timeInfo,
                      PaStreamCallbackFlags statusFlags,
                      void *userData)
{
    paData *data = (paData *)userData;
    float *out = (float *)outputBuffer;
    (void)inputBuffer;

    for (int i = 0; i < framesPerBuffer; i++)
    {
        if (data->play)
        {
            *out++ = 1.0f;
        }
    }
    data->play = 0;

    return 0;
}

int main()
{
    printf("Initializing buzzer\n");

    e(Pa_Initialize());
    outputParameters.device = Pa_GetDefaultOutputDevice();
    if (outputParameters.device == paNoDevice)
    {
        fprintf(stderr, "Error: No default output device.\n");
        return 1;
    }
    outputParameters.channelCount = 1;
    outputParameters.sampleFormat = paFloat32;
    outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
    outputParameters.hostApiSpecificStreamInfo = NULL;
    e(Pa_OpenStream(&stream, NULL, &outputParameters, 44100, 256, paClipOff, paCallback, &data));
    e(Pa_StartStream(stream));

    struct timespec interval;
    interval.tv_sec = 0;
    interval.tv_nsec = 2500000;

    struct timespec pause;

    pause.tv_sec = 2;
    pause.tv_nsec = 0;

    // emulate the black-box to play a 400hz signal
    for (int i = 0; i < 1000; i++)
    {
        data.play = 1;
        nanosleep(&interval, NULL);
    }
    nanosleep(&pause, NULL);

    e(Pa_StopStream(stream));
    e(Pa_CloseStream(stream));
    Pa_Terminate();
}
0

There are 0 best solutions below