#include <alsa/asoundlib.h>
#include <alsa/pcm.h>
#include <math.h>
#define BUFFER_LEN 48000
#define SAMPLE_RATE 48000
#define TONE_FREQUENCY 1000
#define AMPLITUDE 0.8 /* Trim this to get the peak amplitude desired. */
static char *device = "default";
float buffer[BUFFER_LEN];
int main(void)
{
int error = 0, j = 0;
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
/*
* Open the PCM sound device for playback.
*/
if ((error = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
printf("Playback open error: %s\n", snd_strerror(error));
exit(EXIT_FAILURE);
}
/*
* Use float samples, interleaved between left and right (if sending stereo).
*/
if ((error = snd_pcm_set_params(handle,
SND_PCM_FORMAT_FLOAT,
SND_PCM_ACCESS_RW_INTERLEAVED,
1, /* Single stereo channel */
SAMPLE_RATE, /* 48 kHz sample rate */
1, /* Enable soft resampling */
500000)) < 0) { /* 0.5 sec latency */
printf("Playback open error: %s\n", snd_strerror(error));
exit(EXIT_FAILURE);
}
/*
* Fill the buffer with samples based on the math libraries 'sin' function.
* WARNING: this code doesn't handle a complete period of a sine *not* ending
* exactly on the last sample of the sample period. With a 48k sample rate
* and 48k sample buffer, and a 1kHz tone, this isn't an issue. To support
* arbitrary frequencies and arbitrary sample rates this code needs to be
* slightly more complicated, where one would keep track of the phase of
* the sinus as it was at the last sample, and make sure the next buffer
* starts at this point to prevent a discongruety of the signal.
*/
for(j=0; j<BUFFER_LEN; j++){
buffer[j] = AMPLITUDE * sin(2*M_PI*TONE_FREQUENCY/SAMPLE_RATE*j);
}
/*
* We have 48k samples, and a 48 kHz sample rate, so each loop sends
* 1 second of audio.
*/
for (j=0; j<5; j++){
frames = snd_pcm_writei(handle, buffer, BUFFER_LEN);
if (frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
break;
}
}
snd_pcm_close(handle);
return 0;
}