Reputation: 523
I'm learning to use ALSA on a Raspberry Pi 2. I've written a small test program in C++ to generate a 440 Hz test tone. It makes the tone, but there is a clicking sound about twice per second in the tone.
Does anyone have an idea why this might be happening? The code is below.
#include <cmath>
#include <climits>
#include <iostream>
#include <alsa/asoundlib.h>
#include "definitions.hpp"
using namespace std;
int main() {
int ret;
snd_pcm_t* pcm_handle; // device handle
snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
snd_pcm_hw_params_t* hwparams; // hardware information
char* pcm_name = strdup("plughw:0,0"); // on-board audio jack
int rate = 48000;
const uint16 freq = 440;
long unsigned int bufferSize = 8192*4;
const uint32 len = bufferSize*100;
const float32 arg = 2 * 3.141592 * freq / rate;
sint16 vals[len];
for(int i = 0; i < len; i = i + 2) {
vals[i] = SHRT_MAX * cos(arg * i / 2);
}
snd_pcm_hw_params_alloca(&hwparams);
ret = snd_pcm_open(&pcm_handle, pcm_name, stream, 0);
cout << "Opening: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_any(pcm_handle, hwparams);
cout << "Initializing hwparams structure: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_access(pcm_handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
cout << "Setting access: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams,
SND_PCM_FORMAT_S16_LE);
cout << "Setting format: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_rate(pcm_handle, hwparams,
rate, (int)0);
cout << "Setting rate: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2);
cout << "Setting channels: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, 2, 0);
cout << "Setting periods: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams,
&bufferSize);
cout << "Setting buffer size: " << snd_strerror(ret) << endl;
ret = snd_pcm_hw_params(pcm_handle, hwparams);
cout << "Applying parameters: " << snd_strerror(ret) << endl;
cout << endl << endl;
const void* ptr = (const void*)&vals;
int err;
do {
ptr += bufferSize;
ret = snd_pcm_writei(pcm_handle,
ptr, len);
if(ret < 0) {
err = snd_pcm_prepare(pcm_handle);
cout << "Preparing: " << snd_strerror(err)
<< endl;
}
} while(ret < 0);
cout << "Writing data: " << ret << ", " << snd_strerror(ret)
<< endl;
}
When you run it, you get this terminal output. Of course, there's no write error, just the number of bits written.
pi@raspberrypi:~/radio $ ./bin/alsatest
Opening: Success
Initializing hwparams structure: Success
Setting access: Success
Setting format: Success
Setting rate: Success
Setting channels: Success
Setting periods: Success
Setting buffer size: Success
Applying parameters: Success
Writing data: 344110, Unknown error 344110
UPDATE - NEXT DAY OK. I've hooked the output up to my handy-dandy oscilloscope and saw the following waveform. There seems to be a discontinuity in the signal every time there's a click. I added a few lines to count how many nearly-zero values were next to each other in my sinusoid array, and there were none. Oddly enough, the ALSA sample program /test/pcm.c makes a perfect wave. Perhaps I need to write in really small chunks? There doesn't seem to be much difference between my code and the example.
Upvotes: 4
Views: 1443