One way (which would be suitable since you want to target Linux too) would be to generate a WAV file, then play that. (There are simple ways to play WAV files on both Windows and Linux.)
You could use a library to generate the WAV file, or create it yourself, both approaches are pretty simple. There are many examples on the web.
If you do it yourself:
/* WAV header, 44 bytes */
struct wav_header {
uint32_t riff packed;
uint32_t len packed;
uint32_t wave packed;
uint32_t fmt packed;
uint32_t flen packed;
uint16_t one packed;
uint16_t chan packed;
uint32_t hz packed;
uint32_t bpsec packed;
uint16_t bpsmp packed;
uint16_t bitpsmp packed;
uint32_t dat packed;
uint32_t dlen packed;
};
Initialize with:
void wav_header(wav_header *p, uint32_t dlen)
{
memcpy(p->riff, "RIFF", 4);
p->len = dlen + 44;
memcpy(p->wave, "WAVE", 4);
memcpy(p->fmt, "fmt ", 4);
p->flen = 0x10;
p->one = 1;
p->chan = 1;
p->hz = 22050;
p->bpsec = hz;
p->bpsmp = 1;
p->bitpsmp = 8;
memcpy(p->dat, "data", 4);
p->dlen = dlen;
}