Hi All,
I have written an ALSA output program which is producing garbled results.
The results are the same when I wrote an equivalent program using
RtAudio / ALSA.
The platform is an RK3066 based stick computer running Picuntu.
The sound file is processed by sndfile. Playing a sin wav at 375 Hz also
produces unexpected results.
Playing the sound file with aplay works fine.
The sound file is verified to be a 32 bit float sampled at 48KHz and is
monophonic as evidenced by this output:
> Number of channels: 1
> Sample rate: 48000
> Format: 10006
> Alsa device plughw:0,0 is open.
> Rate set to: 48000
> Buffer time set to: 2666
> Direction set to: 1
> Parameters are set.
> Audio interface is prepared.
> Exiting.
Given that aplay uses the hardware correctly and I believe is using
sndfile to parse the file as I am, I am confused as to why RtAudio and
ALSA-direct plays the same garbled result. This suggests a bad
interaction between snfile and the ALSA subsystem caused by me (but I
don't know where).
In my application, I will be processing 48KHz signals only, at 128 float
(stereo or mono) samples at a time.
Here is the code - could someone offer advice?
#include
#include
#include
#include
#include
#include
using namespace std;
#defineNSAMPLES128
float buffer[NSAMPLES];
snd_pcm_t * playback_handle = NULL;
snd_pcm_hw_params_t * hw_params = NULL;
SNDFILE * sndfile = NULL;
SF_INFO sfinfo;
static char *playback_device = (char *) "plughw:0,0";
void SndFileClose()
{
if (sndfile != NULL)
{
sf_close(sndfile);
}
}
bool SndFileOpen(char * file_name)
{
memset(&sfinfo, 0, sizeof(SF_INFO));
if ((sndfile = sf_open(file_name, SFM_READ, &sfinfo)) == NULL)
{
cerr << "Opening: " << file_name << " failed - " <<
sf_strerror(NULL) << endl;
return false;
}
if (sfinfo.channels < 1 || sfinfo.channels > 2)
{
cerr << "Number of channels in: " << file_name << " is: " <<
sfinfo.channels << endl;
SndFileClose();
return false;
}
cout << "Number of channels: " << sfinfo.channels << endl;
cout << "Sample rate: " << sfinfo.samplerate << endl;
cout << "Format: " << hex << sfinfo.format << dec << endl;
return true;
}
int main(int argc, char * argv[])
{
if (argc < 2)
{
cout << "usage: " << argv[0] << " " << endl;
return -1;
}
if (!SndFileOpen(argv[1]))
{
return -1;
}
int err;
if ((err = snd_pcm_open (&playback_handle, playback_device,
SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
cout << "Cannot open audio device " << playback_device << endl;
cout << snd_strerror(err) << endl;
SndFileClose();
return -1;
}
cout << "Alsa device " << playback_device << " is open." << endl;
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
{
cout << "Cannot allocate hardware parameter structure: " << endl;
cout << snd_strerror(err) << endl;
snd_pcm_close(playback_handle);
SndFileClose();
return -1;
}
if ((err = snd_pcm_hw_params_any(playback_handle, hw_params)) < 0)
{
cout << "Cannot initialize hardware parameter structure: " << endl;
cout << snd_strerror(err) << endl;
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(playback_handle);
SndFileClose();
return -1;
}
// NONINTERLEAVED as for this test I know I am writing MONO.
if ((err = snd_pcm_hw_params_set_access(playback_handle, hw_params,
SND_PCM_ACCESS_RW_NONINTERLEAVED)) < 0)
{
cout << "Cannot set access type: " << endl;
cout << snd_strerror (err) << endl;
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(playback_handle);
SndFileClose();
return -1;
}
// Also tried SND_PCM_FORMAT_FLOAT. RK3066 appears to be LE.
if ((err = snd_pcm_hw_params_set_format (playback_handle,
hw_params, SND_PCM_FORMAT_FLOAT_LE)) < 0) {
fprintf (stderr, "cannot set sample format (%s)\n",
snd_strerror (err));
exit (1);
}
unsigned int rate = 48000;
if ((err = snd_pcm_hw_params_set_rate_near(playback_handle,
hw_params, &rate, 0)) < 0)
{
cout << "Cannot set sample rate (48000):" << endl;
cout << snd_strerror (err) << endl;
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(playback_handle);
SndFileClose();
return -1;
}
cout << "Rate set to: " << rate << endl;
// This test is MONO only.
if ((err = snd_pcm_hw_params_set_channels(playback_handle,
hw_params, 1)) < 0)
{
cout << "Cannot set channel count to 1:" << endl;
cout << snd_strerror (err) << endl;
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(playback_handle);
SndFileClose();
return -1;
}
// I am u