LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 05-03-2010, 10:32 AM   #1
aayu09
Member
 
Registered: Feb 2010
Posts: 30

Rep: Reputation: 15
Smile ALSA: snd_pcm_hw_params() failure - Invalid argument


I am working on a ALSA project, and I have a TV tunner card plugged intot the PCI interface. I try to capture the audio from the tunner card, and the followings are the code:

Code:
 
int main()
{
....
snd_pcm_t *tunerAudioHandle = NULL;
snd_pcm_hw_params_t *tunerAudioParams = NULL;
int err;
int blocksz = 32000;
char block[blocksz];
unsigned sampleValue = 32000;

if ((err = snd_pcm_open(&tunerAudioHandle, "hw:1,0", SND_PCM_STREAM_CAPTURE, 0)) < 0)
        {
                printf("could not open tunerAudio device hw:1,0, tunerAudioHandle:%s\n",snd_strerror(err));
                exit (-1);
        }

        if ((err = snd_pcm_hw_params_malloc(&tunerAudioParams)) < 0)
        {
                   printf("could not allocate tunerAudio hardware parameter structur:%s\n",snd_strerror(err));
                   exit (-1);
        }

        if ((err = snd_pcm_hw_params_any(tunerAudioHandle, tunerAudioParams)) < 0)
         {
                 printf("could not initialize tunerAudio parameter structure:%s\n",snd_strerror(err));
                 exit (-1);
         }


         if ((err = snd_pcm_hw_params_set_format(tunerAudioHandle, tunerAudioParams, SND_PCM_FORMAT_S16_LE)) < 0)
         {
                 printf("could not set TunerAudio sample format:%s\n",snd_strerror(err));
                 exit (-1);
         }

         if ((err = snd_pcm_hw_params_set_rate_near(tunerAudioHandle, tunerAudioParams, &sampleValue, 0)) < 0)
         {
                 printf("could not set audioTuner sample rate:%s\n",snd_strerror(err));
                 exit (-1);
         }

         if ((err = snd_pcm_hw_params_set_channels(tunerAudioHandle, tunerAudioParams, 2)) < 0)
         {
                  printf("could not set tunerAudio channels:%s\n",snd_strerror(err));
                  exit (-1);
         }

        printf("set audioTunner channels success!\n");

        if ((err = snd_pcm_hw_params(tunerAudioHandle, tunerAudioParams)) < 0)
        {
                  printf("could not set audioTuner parameter:%s\n",snd_strerror(err));
                  exit (-1);
        }
        printf("set autioTunner pameter success!!\n");
...
}  //end of main
I got the following error message:

Code:
set audioTunner channels success!
could not set audioTuner parameter:Invalid argument
Not sure why failed to set hw parameters for the device. Any help will be appriciated.

-ay
 
Old 05-03-2010, 03:36 PM   #2
piotreks
LQ Newbie
 
Registered: Oct 2009
Posts: 3

Rep: Reputation: 1
Quote:
Originally Posted by aayu09 View Post
I am working on a ALSA project, and I have a TV tunner card plugged intot the PCI interface. I try to capture the audio from the tunner card, and the followings are the code:

Code:
 
...
unsigned sampleValue = 32000;
...
         if ((err = snd_pcm_hw_params_set_rate_near(tunerAudioHandle, tunerAudioParams, &sampleValue, 0)) < 0)
         {
                 printf("could not set audioTuner sample rate:%s\n",snd_strerror(err));
                 exit (-1);
         }
...
        if ((err = snd_pcm_hw_params(tunerAudioHandle, tunerAudioParams)) < 0)
        {
                  printf("could not set audioTuner parameter:%s\n",snd_strerror(err));
                  exit (-1);
        }
I got the following error message:

Code:
set audioTunner channels success!
could not set audioTuner parameter:Invalid argument
Not sure why failed to set hw parameters for the device.
Are you sure the device supports a sampling rate of 32kHz with little-endian 16-bit signed integer sample?

One thing you can try to narrow down the cause is to print out the actual value of the error from 'err = snd_pcm_hw_params...' and then look it up in errno.h.

Good luck.
Pete
 
Old 05-03-2010, 05:14 PM   #3
aayu09
Member
 
Registered: Feb 2010
Posts: 30

Original Poster
Rep: Reputation: 15
Pete:

Thanks for your suggestion. I just confirmed that audio data of S16_LE (signed 16, little-endian) is correct, 32K sample rate is also fine. I just printed out the err num = -22. I did a search and have not found errno.h yet. Do you happen to have the link for errno.h? I am using Fedora Linux 2.6.

Thanks again,

-ay
 
Old 05-04-2010, 06:49 AM   #4
piotreks
LQ Newbie
 
Registered: Oct 2009
Posts: 3

Rep: Reputation: 1
Quote:
Originally Posted by aayu09 View Post
Pete:

Thanks for your suggestion. I just confirmed that audio data of S16_LE (signed 16, little-endian) is correct, 32K sample rate is also fine. I just printed out the err num = -22. I did a search and have not found errno.h yet. Do you happen to have the link for errno.h? I am using Fedora Linux 2.6.
The error code corresponds to the negative of EINVAL #define in /usr/include/asm-generic/errno-base.h.

Here are a few more things to try:
1) Make sure you have access mode set to interleaved, like so:
Code:
if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
			fprintf (stderr, "cannot set access type (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
The above excerpt was taken from here.

2) After setting all the values in the hw_params, try getting them via their corresponding functions and printing them out before sending them to the handle. This way, you'll be sure that all the values you set are there.

Good luck!
Pete
 
Old 05-04-2010, 12:39 PM   #5
aayu09
Member
 
Registered: Feb 2010
Posts: 30

Original Poster
Rep: Reputation: 15
Smile

I have added a few printf commands to query the tv tuner card status. Please see the code and the output.

Code:
//open tunerAudio and set parameters
        if ((err = snd_pcm_open(&tunerAudioHandle, "hw:1,0", SND_PCM_STREAM_CAPTURE, 0)) < 0)
        {
                printf("could not open tunerAudio device hw:1,0, tunerAudioHandle:%s\n",snd_strerror(err));
                exit (-1);
        }

        if ((err = snd_pcm_hw_params_malloc(&tunerAudioParams)) < 0)
        {
                   printf("could not allocate tunerAudio hardware parameter structur:%s\n",snd_strerror(err));
                   exit (-1);
        }

        if ((err = snd_pcm_hw_params_any(tunerAudioHandle, tunerAudioParams)) < 0)
         {
                 printf("could not initialize tunerAudio parameter structure:%s\n",snd_strerror(err));
                 exit (-1);
         }

        if (( err = snd_pcm_hw_params_set_access(tunerAudioHandle, tunerAudioParams, SND_PCM_ACCESS_RW_INTERLEAVED)) <0 )
        {
            printf("could not set access mode as INTERLEAVED.\n");
            exit(-1);
        }
        printf("access mode set as INTERLEAVED success!\n");

         if ((err = snd_pcm_hw_params_set_format(tunerAudioHandle, tunerAudioParams, SND_PCM_FORMAT_S16_LE)) < 0)
         {
                 printf("could not set TunerAudio sample format:%s\n",snd_strerror(err));
                 exit (-1);
         }

         exactRate = sampleRate;
         if ((err = snd_pcm_hw_params_set_rate_near(tunerAudioHandle, tunerAudioParams, &exactRate, 0)) < 0)
         {
                 printf("could not set tuneAudio sample rate:%s\n",snd_strerror(err));
                 exit (-1);
         }

         if (sampleRate != exactRate)
         {
             printf("The rate %d Hz is not supported by your hardware. \n ==> Using %d Hz insteatd.\n",
                 sampleRate, exactRate);
             exit(-1);

         }
         printf("Set tunerAudio rate success! \n");


         if ((err = snd_pcm_hw_params_set_channels(tunerAudioHandle, tunerAudioParams, 2)) < 0)
         {
                  printf("could not set tunerAudio channels:%s\n",snd_strerror(err));
                  exit (-1);
         }

        printf("set audioTunner channels success!\n");

        //set buffer sieze
        if ((err = snd_pcm_hw_params_set_buffer_size(tunerAudioHandle, tunerAudioParams, (periodsize*periods) >> 2)) < 0)
          {
            printf("could not set buffersize.\n");
            exit(-1);
          }
        printf("set tunerAudio buffersize success!\n");

        unsigned int val;
        unsigned int dir, frames;

        //display tunerAudio card parameters
        printf("tunerAudio card handler name = %s\n", snd_pcm_name(tunerAudioHandle));
        printf("tunerAudio pcm state = %s\n",
            snd_pcm_state_name(snd_pcm_state(tunerAudioHandle)));

        snd_pcm_hw_params_get_access(tunerAudioParams, (snd_pcm_access_t *) &val);
        printf("tunerAudio access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));

        snd_pcm_hw_params_get_format(tunerAudioParams, &val);
        printf("tunerAudio format = %s (%s)\n", snd_pcm_format_name((snd_pcm_format_t) val),
            snd_pcm_format_description((snd_pcm_format_t) val));

        snd_pcm_hw_params_get_format(tunerAudioParams, &val);
         printf("format = '%s' (%s)\n", snd_pcm_format_name((snd_pcm_format_t)val),
             snd_pcm_format_description((snd_pcm_format_t)val));

        snd_pcm_hw_params_get_subformat(tunerAudioParams, (snd_pcm_subformat_t *)&val);
         printf("subformat = '%s' (%s)\n", snd_pcm_subformat_name((snd_pcm_subformat_t)val),
             snd_pcm_subformat_description((snd_pcm_subformat_t)val));

         snd_pcm_hw_params_get_channels(tunerAudioParams, &val);
         printf("channels = %d\n", val);

         snd_pcm_hw_params_get_rate(tunerAudioParams, &val, &dir);
         printf("rate = %d bps\n", val);

         snd_pcm_hw_params_get_period_time(tunerAudioParams, &val, &dir);
         printf("period time = %d us\n", val);

         snd_pcm_hw_params_get_period_size(tunerAudioParams, &frames, &dir);
         printf("period size = %d frames\n", (int)frames);

         snd_pcm_hw_params_get_buffer_time(tunerAudioParams, &val, &dir);
         printf("buffer time = %d us\n", val);

         snd_pcm_hw_params_get_buffer_size(tunerAudioParams,(snd_pcm_uframes_t *) &val);
         printf("buffer size = %d frames\n", val);

         snd_pcm_hw_params_get_periods(tunerAudioParams, &val, &dir);
         printf("periods per buffer = %d frames\n", val);


        //set number of periods
  /*     if ((err = snd_pcm_hw_params_set_periods(tunerAudioHandle, tunerAudioParams, (snd_pcm_uframes_t){ 512 }, 0)) < 0)
          {
            printf("could not set tunerAudio periods.\n");
            exit(-1);
          }
        printf("set tunerAudio periods success!\n");
*/
        if ((err = snd_pcm_hw_params(tunerAudioHandle, tunerAudioParams)) < 0)
        {
                  printf("could not set audioTuner HW parameter:%s, error num = %d\n",snd_strerror(err), err);
                  exit (-1);
        }
        printf("set autioTunner HW pameter success!!\n");
        snd_pcm_hw_params_free(tunerAudioParams);
The output are as follows:

Code:
[root@mu153097 dtvScan]# ./kwaud
access mode set as INTERLEAVED success!
Set tunerAudio rate success!
set audioTunner channels success!
set tunerAudio buffersize success!
tunerAudio card handler name = hw:1,0
tunerAudio pcm state = OPEN
tunerAudio access type = RW_INTERLEAVED
tunerAudio format = S16_LE (Signed 16 bit Little Endian)
format = 'S16_LE' (Signed 16 bit Little Endian)
subformat = 'STD' (Standard)
channels = 2
rate = 32000 bps
period time = 32000 us
period size = 11452372 frames
buffer time = 128000 us
buffer size = 4096 frames
periods per buffer = 4096 frames
could not set audioTuner HW parameter:Invalid argument, error num = -22
I suspect that the error might be related to the setting of those parameters, e.g. rate, period time, period size, buffer size etc. But I am not sure about that.
 
Old 05-04-2010, 04:19 PM   #6
aayu09
Member
 
Registered: Feb 2010
Posts: 30

Original Poster
Rep: Reputation: 15
Smile

I found the problem was caused by not setting the proper buffersize and period size. After calling the snd_pcm_hw_params_set_buffer_size() and snd_pcm_hw_params_set_period_size(). It worked fine. See the following output:
Code:
access mode set as INTERLEAVED success!
Set tunerAudio rate success!
set audioTunner channels success!
set tunerAudio buffer size success!
set tunerAudio period size success!
tunerAudio card handler name = hw:1,0
tunerAudio pcm state = OPEN
tunerAudio access type = MMAP_INTERLEAVED
tunerAudio format = S16_LE (Signed 16 bit Little Endian)
format = 'S16_LE' (Signed 16 bit Little Endian)
subformat = 'STD' (Standard)
channels = 2
rate = 32000 bps
period time = 16000 us
period size = 512 frames
buffer time = 512000 us
buffer size = 16384 frames
periods per buffer = 32 frames
set autioTunner HW pameter success!!
 
Old 05-05-2010, 08:36 AM   #7
piotreks
LQ Newbie
 
Registered: Oct 2009
Posts: 3

Rep: Reputation: 1
Quote:
Originally Posted by aayu09 View Post
I found the problem was caused by not setting the proper buffersize and period size. After calling the snd_pcm_hw_params_set_buffer_size() and snd_pcm_hw_params_set_period_size(). It worked fine.
Awesome!!!!
Glad you got it working!
P
 
Old 05-29-2012, 01:14 AM   #8
gbmkrao
LQ Newbie
 
Registered: May 2012
Posts: 1

Rep: Reputation: Disabled
snd_pcm_hw_params_set_format : error: -22

I am also getting the same error: -22 for snd_pcm_hw_params_set_format with SND_PCM_FORMAT_S16_LE. Could some please explain how to set proper parameters (like buffer size, period size...). Did these these parameters depends on audio card (hardware specific)?

please check the code below i am using now.
code:

snd_pcm_t *pcm;

assert(snd_pcm_open(&pcm, name, SND_PCM_STREAM_CAPTURE, 0) == 0);

snd_pcm_hw_params_t *pcm_hw_params;

assert(snd_pcm_hw_params_malloc(&pcm_hw_params) == 0);

assert(snd_pcm_hw_params_any(pcm, pcm_hw_params) == 0);

assert(snd_pcm_hw_params_set_access(pcm, pcm_hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED) == 0);

assert(snd_pcm_hw_params_set_buffer_size(pcm, pcm_hw_params, 16384) == 0);

assert(snd_pcm_hw_params_set_period_size(pcm, pcm_hw_params, (snd_pcm_uframes_t){ 1024 }, (int){ 0 }) == 0);

assert(snd_pcm_hw_params_set_format(pcm, pcm_hw_params, SND_PCM_FORMAT_S16_LE) == 0);
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
invalid argument azza Programming 1 07-01-2009 09:45 PM
invalid argument azza Programming 1 06-29-2009 08:25 AM
message sending failed : Error[22 ] invalid argument .....but each and every argument rakeshranjanjha Linux - Software 2 01-07-2008 11:22 PM
alsa mixer sayin "function snd_mixer_load failed:invalid argument" callmeleroi Fedora 0 03-11-2007 09:05 AM
xawtv - invalid argument liguorir Linux - Software 0 06-17-2003 08:55 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 06:57 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration