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 <iostream> #include <unistd.h> #include <cstring> #include <math.h> #include <alsa/asoundlib.h> #include <sndfile.h> using namespace std; #define NSAMPLES 128 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] << " <soundfile>" << 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 uncertain what buffer and period time do. The value below is // 128 / 48000 seconds expressed in microseconds. Adding the call // to set_buffer_time_near() did not improve or change the results. unsigned int buffer_time = int(1.0f / 48000.0f * 128.0f * 1000000.0f); int direction = 1; if ((err = snd_pcm_hw_params_set_buffer_time_near(playback_handle, hw_params, &buffer_time, &direction)) < 0) { cout << "Cannot set buffer time:" << endl; cout << snd_strerror (err) << endl; snd_pcm_hw_params_free(hw_params); snd_pcm_close(playback_handle); SndFileClose(); return -1; } cout << "Buffer time set to: " << buffer_time << endl; cout << "Direction set to: " << direction << endl; if ((err = snd_pcm_hw_params(playback_handle, hw_params)) < 0) { cout << "Cannot set parameters:" << endl; cout << snd_strerror (err) << endl; snd_pcm_hw_params_free(hw_params); snd_pcm_close(playback_handle); SndFileClose(); return -1; } cout << "Parameters are set." << endl; if ((err = snd_pcm_prepare(playback_handle)) < 0) { cout << "Cannot prepare audio interface for use:" << endl; cout << snd_strerror (err) << endl; snd_pcm_hw_params_free(hw_params); snd_pcm_close(playback_handle); SndFileClose(); return -1; } cout << "Audio interface is prepared." << endl; int frames_read; void * buffer_array[1]; buffer_array[0] = (void *) buffer; while ((frames_read = sf_readf_float(sndfile, buffer, NSAMPLES)) != 0) { if ((snd_pcm_writen(playback_handle, buffer_array, frames_read)) != frames_read) { cout << "Write to audio interface failed:" << endl; cout << snd_strerror (err) << endl; snd_pcm_hw_params_free(hw_params); snd_pcm_close(playback_handle); SndFileClose(); return -1; } } cout << "Exiting." << endl; snd_pcm_hw_params_free (hw_params); snd_pcm_close(playback_handle); SndFileClose(); return 0; } -- Perry Kivolowitz, VES ------------------------------------------------------------------------------ AlienVault Unified Security Management (USM) platform delivers complete security visibility with the essential security capabilities. Easily and efficiently configure, manage, and operate all of your security controls from a single console and one unified framework. Download a free trial. http://p.sf.net/sfu/alienvault_d2d _______________________________________________ Alsa-user mailing list Alsa-user@xxxxxxxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/alsa-user