LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 01-10-2008, 02:59 AM   #1
muskvar
Member
 
Registered: May 2007
Posts: 54

Rep: Reputation: 15
Programming with ALSA API


i took a program from paul's tutorial on the ALSA API:

here is the code called alsasound.c:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
	      
	main (int argc, char *argv[])
	{
		int i;
		int err;
		short buf[128];
		snd_pcm_t *playback_handle;
		snd_pcm_hw_params_t *hw_params;
	
		if ((err = snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
			fprintf (stderr, "cannot open audio device %s (%s)\n", 
				 argv[1],
				 snd_strerror (err));
			exit (1);
		}
		   
		if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
			fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
				 
		if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) {
			fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
			fprintf (stderr, "cannot set access type (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
			fprintf (stderr, "cannot set sample format (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		if ((err = snd_pcm_hw_params_set_rate_near (playback_handle, hw_params, 44100, 0)) < 0) {
			fprintf (stderr, "cannot set sample rate (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 2)) < 0) {
			fprintf (stderr, "cannot set channel count (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) {
			fprintf (stderr, "cannot set parameters (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		snd_pcm_hw_params_free (hw_params);
	
		if ((err = snd_pcm_prepare (playback_handle)) < 0) {
			fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
				 snd_strerror (err));
			exit (1);
		}
	
		for (i = 0; i < 10; ++i) {
			if ((err = snd_pcm_writei (playback_handle, buf, 128)) != 128) {
				fprintf (stderr, "write to audio interface failed (%s)\n",
					 snd_strerror (err));
				exit (1);
			}
		}
	
		snd_pcm_close (playback_handle);
		exit (0);
	}
i compiled it as:
gcc -I /home/muskvar/alsa/include alsasound.c -lasound

it compiled without any problems but when i ran the program i got this error:

a.out: pcm.c:2171: snd_pcm_open: Assertion `pcmp && name' failed.

i have no idea as to what this means and how it can be resolved.

please help!!
 
Old 01-10-2008, 04:10 AM   #2
muskvar
Member
 
Registered: May 2007
Posts: 54

Original Poster
Rep: Reputation: 15
i have got around and solved the running problem by using this code:

Code:
*

This example reads standard from input and writes
to the default PCM device for 5 seconds of data.

*/

/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API

#include <alsa/asoundlib.h>

int main() {
  long loops;
  int rc;
  int size;
  snd_pcm_t *handle;
  snd_pcm_hw_params_t *params;
  unsigned int val;
  int dir;
  snd_pcm_uframes_t frames;
  char *buffer;

  /* Open PCM device for playback. */
  rc = snd_pcm_open(&handle, "default",
                    SND_PCM_STREAM_PLAYBACK, 0);
  if (rc < 0) {
    fprintf(stderr,
            "unable to open pcm device: %s\n",
            snd_strerror(rc));
    exit(1);
  }

  /* Allocate a hardware parameters object. */
  snd_pcm_hw_params_alloca(&params);

  /* Fill it in with default values. */
  snd_pcm_hw_params_any(handle, params);

  /* Set the desired hardware parameters. */

  /* Interleaved mode */
  snd_pcm_hw_params_set_access(handle, params,
                      SND_PCM_ACCESS_RW_INTERLEAVED);

  /* Signed 16-bit little-endian format */
  snd_pcm_hw_params_set_format(handle, params,
                              SND_PCM_FORMAT_S16_LE);

  /* Two channels (stereo) */
  snd_pcm_hw_params_set_channels(handle, params, 2);

  /* 44100 bits/second sampling rate (CD quality) */
  val = 44100;
  snd_pcm_hw_params_set_rate_near(handle, params,
                                  &val, &dir);

  /* Set period size to 32 frames. */
  frames = 32;
  snd_pcm_hw_params_set_period_size_near(handle,
                              params, &frames, &dir);

  /* Write the parameters to the driver */
  rc = snd_pcm_hw_params(handle, params);
  if (rc < 0) {
    fprintf(stderr,
            "unable to set hw parameters: %s\n",
            snd_strerror(rc));
    exit(1);
  }

  /* Use a buffer large enough to hold one period */
  snd_pcm_hw_params_get_period_size(params, &frames,
                                    &dir);
  size = frames * 4; /* 2 bytes/sample, 2 channels */
  buffer = (char *) malloc(size);

  /* We want to loop for 5 seconds */
  snd_pcm_hw_params_get_period_time(params,
                                    &val, &dir);
  /* 5 seconds in microseconds divided by
   * period time */
  loops = 5000000 / val;

  while (loops > 0) {
    loops--;
    rc = read(0, buffer, size);
    if (rc == 0) {
      fprintf(stderr, "end of file on input\n");
      break;
    } else if (rc != size) {
      fprintf(stderr,
              "short read: read %d bytes\n", rc);
    }
    rc = snd_pcm_writei(handle, buffer, frames);
    if (rc == -EPIPE) {
      /* EPIPE means underrun */
      fprintf(stderr, "underrun occurred\n");
      snd_pcm_prepare(handle);
    } else if (rc < 0) {
      fprintf(stderr,
              "error from writei: %s\n",
              snd_strerror(rc));
    }  else if (rc != (int)frames) {
      fprintf(stderr,
              "short write, write %d frames\n", rc);
    }
  }

  snd_pcm_drain(handle);
  snd_pcm_close(handle);
  free(buffer);

  return 0;
}
now when i run this program as:
./a.out < 32a5.mp3
(where 32a5 is a short mp3 file)

i only get some white noise.

how do i solve this problem.


Please help urgently.
 
Old 01-10-2008, 08:37 PM   #3
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 64
Quote:
Originally Posted by muskvar View Post
now when i run this program as:
./a.out < 32a5.mp3
(where 32a5 is a short mp3 file)

i only get some white noise.
Your pcm device was opened as SND_PCM_STREAM_PLAYBACK, and you have set the parameters for SND_PCM_FORMAT_S16_LE (signed, 16-bit, little-endian PCM sound) at 44.1kHz. You can’t expect raw mp3 data to magically conform to this format. You will either need to decode the mp3 yourself or find some other sound files which are in signed, 16-bit, little-endian PCM format at 44.1kHz.
 
Old 01-11-2008, 02:37 AM   #4
muskvar
Member
 
Registered: May 2007
Posts: 54

Original Poster
Rep: Reputation: 15
Mr.osor,

could you please elaborate on what you just said because i am just a newbie fascinated by this concept.

how can i decode an MP3 file as you said or how will i know if a download MP3 or any other file is coded in signed 16bit format?

good day,
 
Old 01-15-2008, 07:15 AM   #5
muskvar
Member
 
Registered: May 2007
Posts: 54

Original Poster
Rep: Reputation: 15
somebody please pay heed to my question.

please help me.

good day.
 
Old 01-15-2008, 12:25 PM   #6
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 64
You’ll have two options if you want to decode the file: do it internally or external of the program. The easiest is to do it externally. For example,
Code:
madplay -owave:- 32a5.mp3 | ./a.out
would use the external mp3 decoder madplay (which interally uses libmad).

Alternatively, you could decode the stream yourself (in the program). This would most likely use an already-existing decoding library (such as libmad). If you don’t want to use an already-existing decoding library, you’ll have to read the MPEG specifications to figure out the format, and how it should convert to PCM. Then, you’ll have to write all the processing code yourself.
 
Old 01-15-2008, 12:31 PM   #7
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 64
Btw, if you want to find the encoding of a file, most of them use magic bytes, and are suitable for use with file. The extension for MPEG, Layer-III audio encoding is usually “.mp3” (as you would expect). The extension for PCM audio varies, but is usually “.wav”, “.aiff”, “.au”, or “.raw”. Here’s what file tells me on my machine:
Code:
$ file foo.mp3
foo.mp3: Audio file with ID3 version 24.0 tag, MP3 encoding
$ file foo.wav
foo.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
 
Old 07-19-2008, 04:08 PM   #8
Jessard
Member
 
Registered: Jun 2005
Location: Boston, USA
Distribution: Gentoo, CentOS
Posts: 82

Rep: Reputation: 16
Just for the record:

In my struggles with ALSA I was having the same problem as muskvar initially had, with "a.out: pcm.c:2171: snd_pcm_open: Assertion `pcmp && name' failed."

Once I finally looked at the call to snd_pcm_open in the example code, though, I noticed the second argument is argv[1] ! It's assuming the command-line argument to the program is the ALSA device name you want to use. So just run "./a.out default" (or something; "aplay -L" gives a list of device names available) instead of "./a.out" and it should work as expected.
 
Old 06-12-2009, 08:30 PM   #9
dchou4u
LQ Newbie
 
Registered: Nov 2004
Distribution: Fedora Core 2
Posts: 9

Rep: Reputation: 0
where is snd_pcm_writei() defined?

I am running 2.6.19 on an ARM target board. I want to enable ALSA sound support. Where is snd_pcm_writei() defined in the source tree?

Thanks
 
Old 12-15-2009, 02:40 PM   #10
theinvisibleguy3
LQ Newbie
 
Registered: Nov 2009
Posts: 3

Rep: Reputation: 0
dchou4u, snd_pcm_writei is defined in asoundlib.h, this can be found in /usr/include/alsa. To enable this for arm support the easiest way is to just move that alsa directory to your include location in gcc that you are using to compile for the arm target. Additionally you will need the alsa library, you can compile this yourself or if alsa is already on your arm board just search for libasound.so and copy it to the /lib directory you are using to compile.
 
  


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
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ALSA programming hobase Programming 0 11-21-2007 05:44 PM
ALSA plugin programming question evilquesadilla Programming 0 10-24-2007 05:44 AM
ALSA API and C lib mykaitch Programming 1 02-24-2007 01:20 AM
Need to find an API for programming NetBEUI under Window paulsm4 Programming 3 03-07-2006 09:23 AM


All times are GMT -5. The time now is 07:53 PM.

Main Menu
 
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
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration