* I thought it would simple.... @ 2003-07-23 6:54 Tom Watson 2003-07-23 11:07 ` Carlo Wood 0 siblings, 1 reply; 5+ messages in thread From: Tom Watson @ 2003-07-23 6:54 UTC (permalink / raw) To: alsa development I am attempting to write a "simple" audio playback program. Well, I thought it would be, but... Somehow (thru strace) the 'snd_pcm_writei' call goes and eventually does a system 'poll' call, but it doesn't return indicating that a write is OK to do. I've used similar parameters in 'aplay' and I see that it works. The basis of the program I'm writing is the one described in _A Tutorial on Using the ALSA API_ (http://equalarea.com/paul/alsa-audio.html), section entitled "A Minimal Playback Program". One thing I've noted: Some of the data printed out by "snd_pcm_dump" is different between my program and 'aplay'. I suspect that there is a clue somewhere, but what is the "magic"?? If necessary, I can provide the 'strace' or the output from 'snd_pcm_dump', but in the interest of brevity... Any "great clue" would be appreciated. Thanks. ===== -- Tom Watson tsw@johana.com __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ------------------------------------------------------- This SF.net email is sponsored by: VM Ware With VMware you can run multiple operating systems on a single machine. WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the same time. Free trial click here: http://www.vmware.com/wl/offer/345/0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: I thought it would simple.... 2003-07-23 6:54 I thought it would simple Tom Watson @ 2003-07-23 11:07 ` Carlo Wood 2003-07-24 5:03 ` Tom Watson 0 siblings, 1 reply; 5+ messages in thread From: Carlo Wood @ 2003-07-23 11:07 UTC (permalink / raw) To: tsw; +Cc: alsa development [-- Attachment #1: Type: text/plain, Size: 1699 bytes --] I found that a better example for playback is the 'pcm.c' file that you can find on the alsa site. It contains many ways to deliver the data (a nice sine) to your soundcard. Playing with the parameters gives some insight (more than reading the overall poor documentation imho :(). Anyway - I "translated" the one you mention to C++; it works for me. I'll include it below. Compile like: g++ playback.cc -lasound For me, this gives a lot of buffer overruns... pcm.c doesn't suffer from that. Note that I added: dir = 0; // ??? According to valgrind, this value is USED (read) for a conditional jump! Maybe that is a bug of alsa, maybe it is just badly documented - but to be safe you should set that variable too. On Tue, Jul 22, 2003 at 11:54:49PM -0700, Tom Watson wrote: > I am attempting to write a "simple" audio playback program. Well, I > thought it would be, but... > Somehow (thru strace) the 'snd_pcm_writei' call goes and eventually > does a system 'poll' call, but it doesn't return indicating that a > write is OK to do. > I've used similar parameters in 'aplay' and I see that it works. > > The basis of the program I'm writing is the one described in _A > Tutorial on Using the ALSA API_ > (http://equalarea.com/paul/alsa-audio.html), section entitled "A > Minimal Playback Program". > > One thing I've noted: Some of the data printed out by "snd_pcm_dump" > is different between my program and 'aplay'. I suspect that there is a > clue somewhere, but what is the "magic"?? > > If necessary, I can provide the 'strace' or the output from > 'snd_pcm_dump', but in the interest of brevity... > > Any "great clue" would be appreciated. -- Carlo Wood <carlo@alinoe.com> [-- Attachment #2: playback.cc --] [-- Type: text/plain, Size: 4746 bytes --] #include <alsa/asoundlib.h> #include <iostream> #include <cstring> int main(void) { // Handle for the PCM device. snd_pcm_t* pcm_handle; // Playback stream. snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; // This structure contains information about // the hardware and can be used to specify the // configuration to be used for the PCM stream. snd_pcm_hw_params_t* hwparams; // Name of the PCM device, like plughw:0,0. // The first number is the number of the soundcard, // the second number is the number of the device. char const* pcm_name = "plughw:0,0"; // Allocate the snd_pcm_hw_params_t structure on the stack. snd_pcm_hw_params_alloca(&hwparams); // Open PCM. The last parameter of this function is the mode. // If this is set to 0, the standard mode is used. Possible // other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC. // If SND_PCM_NONBLOCK is used, read / write access to the // PCM device will return immediately. If SND_PCM_ASYNC is // specified, SIGIO will be emitted whenever a period has // been completely processed by the soundcard. if (snd_pcm_open(&pcm_handle, pcm_name, stream, 0) < 0) { std::cerr << "Error opening PCM device " << pcm_name << std::endl; return -1; } // Init hwparams with full configuration space. if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { std::cerr << "Can not configure this PCM device." << std::endl; return -1; } unsigned int rate = 22050; // Sample rate. int exact_rate; // Sample rate returned by snd_pcm_hw_params_set_rate_near. int dir; // exact_rate == rate --> dir = 0 // exact_rate < rate --> dir = -1 // exact_rate > rate --> dir = 1 int periods = 16; // Number of periods. int periodsize = 1024; // Periodsize (bytes). // Set access type. This can be either // SND_PCM_ACCESS_RW_INTERLEAVED or // SND_PCM_ACCESS_RW_NONINTERLEAVED. // There are also access types for MMAPed // access, but this is beyond the scope // of this introduction. if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { std::cerr << "Error setting access." << std::endl; return -1; } // Set sample format to 'Signed 16 bit Little Endian'. if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) { std::cerr << "Error setting format." << std::endl; return(-1); } // Set sample rate. If the exact rate is not supported // by the hardware, use nearest possible rate. dir = 0; // ??? According to valgrind, this value is USED (read) for a conditional jump! exact_rate = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, rate, &dir); if (rate != exact_rate) { std::cerr << "The rate " << rate << " Hz is not supported by your hardware.\n " "==> Using " << exact_rate << " Hz instead." << std::endl; } // Set number of channels. if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) { std::cerr << "Error setting channels." << std::endl; return -1; } // Set number of periods. Periods used to be called fragments. if (snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0) < 0) { std::cerr << "Error setting periods." << std::endl; return -1; } // Set buffer size (in frames). The resulting latency is given by // latency = periodsize * periods / (rate * bytes_per_frame). if (snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, (periodsize * periods) >> 2) < 0) { std::cerr << "Error setting buffersize." << std::endl; return -1; } // Apply HW parameter settings to // PCM device and prepare device. if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) { std::cerr << "Error setting HW params." << std::endl; return -1; } unsigned char* data; int pcmreturn; short s1, s2; int frames; data = (unsigned char*)malloc(periodsize); frames = periodsize >> 2; std::cout << "frames = " << frames << '\n'; for (int l1 = 0; l1 < 100; ++l1) { for (int l2 = 0; l2 < frames; ++l2) { s1 = (l2 % 128) * 100 - 5000; s2 = (l2 % 256) * 100 - 5000; data[4 * l2] = (unsigned char)s1; data[4 * l2 + 1] = s1 >> 8; data[4 * l2 + 2] = (unsigned char)s2; data[4 * l2 + 3] = s2 >> 8; } while ((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0) { if (pcmreturn == -EPIPE) { std::cout << "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>" << std::endl; snd_pcm_prepare(pcm_handle); } else { std::cout << "snd_pcm_writei: " << strerror(-pcmreturn) << '\n'; break; } } std::cout << "pcmreturn = " << pcmreturn << '\n'; } return 0; } ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: I thought it would simple.... 2003-07-23 11:07 ` Carlo Wood @ 2003-07-24 5:03 ` Tom Watson 2003-07-24 13:48 ` Takashi Iwai 0 siblings, 1 reply; 5+ messages in thread From: Tom Watson @ 2003-07-24 5:03 UTC (permalink / raw) To: Carlo Wood, tsw; +Cc: alsa development [-- Attachment #1: Type: text/plain, Size: 2657 bytes --] OK, here is more data. The enclosed files are: 1) The "minimal playback program" described in the original message, modified to clear the buffer, and do the "dump" of the parameters. The buffer size is lengthened a bit (maybe this makes a difference??) 2) The output of 'strace' on the program, it stops at the 'poll' instruction (broken out with a ^c at the terminal). 3) A cut/pasted copy of the output sent to the terminal. In particular, it has the output from "snd_pcm_dump" which ought to help a bit. The source was compiled with 'cc simple.c -lasound -o simple'. It was executed with './simple surround40'. I think I'm doing everything OK, and if I solve this goodie (on the simple program), I suspect tha I can solve the problem with my program. P.S. The sound card is a Turtle Beach Santa Cruz. It can handle the 4 channel things OK (I used 'aplay' very nicely!!) While the C++ program is nice, I'm not really into that. It seemed to work OK (as given). My program is C, thus the enclosed files. Maybe there is a solution out there. Thanks to all. ALSA is the way of the future!! --- Carlo Wood <carlo@alinoe.com> wrote: > I found that a better example for playback is > the 'pcm.c' file that you can find on the alsa site. > It contains many ways to deliver the data (a nice > sine) to your soundcard. Playing with the parameters > gives some insight (more than reading the overall poor > documentation imho :(). > <<<deletia>>> > On Tue, Jul 22, 2003 at 11:54:49PM -0700, Tom Watson wrote: > > I am attempting to write a "simple" audio playback program. Well, > I > > thought it would be, but... > > Somehow (thru strace) the 'snd_pcm_writei' call goes and eventually > > does a system 'poll' call, but it doesn't return indicating that a > > write is OK to do. > > I've used similar parameters in 'aplay' and I see that it works. > > > > The basis of the program I'm writing is the one described in _A > > Tutorial on Using the ALSA API_ > > (http://equalarea.com/paul/alsa-audio.html), section entitled "A > > Minimal Playback Program". > > > > One thing I've noted: Some of the data printed out by > "snd_pcm_dump" > > is different between my program and 'aplay'. I suspect that there > is a > > clue somewhere, but what is the "magic"?? > > > > If necessary, I can provide the 'strace' or the output from > > 'snd_pcm_dump', but in the interest of brevity... > > > > Any "great clue" would be appreciated. <<<deletia of C++ program...>>> ===== -- Tom Watson tsw@johana.com __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com [-- Attachment #2: simple.c --] [-- Type: application/octet-stream, Size: 2474 bytes --] #include <stdio.h> #include <stdlib.h> #include <string.h> #include <alsa/asoundlib.h> #define CHAN 4 #define BSIZ 4096 /* Number of frames */ main (int argc, char *argv[]) { int i; int err; short buf[CHAN * BSIZ]; snd_pcm_t *playback_handle; snd_pcm_hw_params_t *hw_params; snd_output_t *log; /* For the log goodie */ /* Just set it to something empty */ memset (buf, 0, sizeof(buf)); 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, CHAN)) < 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); } err = snd_output_stdio_attach(&log, stderr, 0); if (err < 0) { fprintf (stderr, "Can\'t do stdio attach (%d)\n", err); exit (1); } snd_pcm_dump (playback_handle, log); /* 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, BSIZ)) != BSIZ) { fprintf (stderr, "write to audio interface failed (%s)\n", snd_strerror (err)); exit (1); } } snd_pcm_close (playback_handle); exit (0); } [-- Attachment #3: simple.tr --] [-- Type: application/x-troff, Size: 26330 bytes --] [-- Attachment #4: simple.sout --] [-- Type: application/octet-stream, Size: 1682 bytes --] Multi PCM Channel bindings: 0: slave 0, channel 0 1: slave 0, channel 1 2: slave 1, channel 0 3: slave 1, channel 1 Its setup is: stream : PLAYBACK access : RW_INTERLEAVED format : S16_LE subformat : STD channels : 4 rate : 44100 exact rate : 44100 (44100/1) msbits : 16 buffer_size : 8192 period_size : 8 period_time : 181 tick_time : 10000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 8 xfer_align : 8 start_threshold : 1 stop_threshold : 8192 silence_threshold: 0 silence_size : 0 boundary : 1073741824 Slave #0: Hardware PCM card 0 'Sound Fusion CS46xx' device 0 subdevice 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 2 rate : 44100 exact rate : 44100 (44100/1) msbits : 16 buffer_size : 8192 period_size : 8 period_time : 181 tick_time : 10000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 8 xfer_align : 8 start_threshold : 1 stop_threshold : 8192 silence_threshold: 0 silence_size : 0 boundary : 1073741824 Slave #1: Hardware PCM card 0 'Sound Fusion CS46xx' device 1 subdevice 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 2 rate : 44100 exact rate : 44100 (44100/1) msbits : 16 buffer_size : 8192 period_size : 8 period_time : 181 tick_time : 10000 tstamp_mode : NONE period_step : 1 sleep_min : 0 avail_min : 8 xfer_align : 8 start_threshold : 1 stop_threshold : 8192 silence_threshold: 0 silence_size : 0 boundary : 1073741824 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: I thought it would simple.... 2003-07-24 5:03 ` Tom Watson @ 2003-07-24 13:48 ` Takashi Iwai 2003-08-11 21:30 ` Tom Watson 0 siblings, 1 reply; 5+ messages in thread From: Takashi Iwai @ 2003-07-24 13:48 UTC (permalink / raw) To: tsw; +Cc: alsa-devel At Wed, 23 Jul 2003 22:03:25 -0700 (PDT), Tom Watson wrote: > > OK, here is more data. The enclosed files are: > 1) The "minimal playback program" described in the original message, > modified to clear the buffer, and do the "dump" of the parameters. The > buffer size is lengthened a bit (maybe this makes a difference??) in general, it'd better to specify proper period and buffer sizes in hw_params. (you can use *_near() for that purpose, too, in the case the hardware doesn't support the request size.) note that the configuration of buffer and period sizes is often sensitive to the card type. and they define the stability and the latency of the application. that's why many applications have options to set up these things. also, calling snd_pcm_prepare() is not necessary. it's called automatically after hw_params(). it's needed only after xrun/suspend occurs. many programs have the xrun recovery. in the playback direction, if a buffer underrun occurs, snd_pcm_writei() returns -EPIPE (and -ESTRPIPE if the suspend occurs). and ALSA drivers don't recover this status automatically as default. you need to call snd_pcm_prepare() to recover the status. so, Takashi ------------------------------------------------------- This SF.Net email sponsored by: Free pre-built ASP.NET sites including Data Reports, E-commerce, Portals, and Forums are available now. Download today and enter to win an XBOX or Visual Studio .NET. http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01 ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: I thought it would simple.... 2003-07-24 13:48 ` Takashi Iwai @ 2003-08-11 21:30 ` Tom Watson 0 siblings, 0 replies; 5+ messages in thread From: Tom Watson @ 2003-08-11 21:30 UTC (permalink / raw) To: Takashi Iwai; +Cc: alsa-devel Sorry I could not get back to you... Vacation and travel over 9 time zones in the last 36 hours... The soundcard appears to work quite nicely using 'aplay' (default parameters, but device 'surround40'). I just want to get an idea of what I'm doing that causes this problem. The "sample" program OUGHT to work, after all it is a "sample", isn't it... Maybe there could be a "debugging" version of the library that is similar to "strace" for the library calls. Setting an environment variable (output device file??) turns it on. That way people could analyze the flow thru the library, which is much less verbiage and raw data then the true I/O calls. Maybe an install option, or something in the library. Just an idea. I suspect that if it were available, the sequence used by 'aplay' would be immediately obvious (DUH!), and I could modify my dumb program. In any event, I'll try the suggestions to see what comes next. Anything is possible!! --- Takashi Iwai <tiwai@suse.de> wrote: > At Wed, 23 Jul 2003 22:03:25 -0700 (PDT), > Tom Watson wrote: > > > > OK, here is more data. The enclosed files are: > > 1) The "minimal playback program" described in the original > message, > > modified to clear the buffer, and do the "dump" of the parameters. > The > > buffer size is lengthened a bit (maybe this makes a difference??) > > in general, it'd better to specify proper period and buffer sizes in > hw_params. (you can use *_near() for that purpose, too, in the case > the hardware doesn't support the request size.) > > note that the configuration of buffer and period sizes is often > sensitive to the card type. and they define the stability and the > latency of the application. that's why many applications have > options > to set up these things. > > also, calling snd_pcm_prepare() is not necessary. it's called > automatically after hw_params(). it's needed only after xrun/suspend > occurs. > > many programs have the xrun recovery. in the playback direction, if > a buffer underrun occurs, snd_pcm_writei() returns -EPIPE (and > -ESTRPIPE if the suspend occurs). and ALSA drivers don't recover > this > status automatically as default. you need to call snd_pcm_prepare() > to recover the status. so, > > > Takashi > > > ------------------------------------------------------- > This SF.Net email sponsored by: Free pre-built ASP.NET sites > including > Data Reports, E-commerce, Portals, and Forums are available now. > Download today and enter to win an XBOX or Visual Studio .NET. > http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01 > _______________________________________________ > Alsa-devel mailing list > Alsa-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/alsa-devel ===== -- Tom Watson tsw@johana.com __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ------------------------------------------------------- This SF.Net email sponsored by: Free pre-built ASP.NET sites including Data Reports, E-commerce, Portals, and Forums are available now. Download today and enter to win an XBOX or Visual Studio .NET. http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01 ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2003-08-11 21:30 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-07-23 6:54 I thought it would simple Tom Watson 2003-07-23 11:07 ` Carlo Wood 2003-07-24 5:03 ` Tom Watson 2003-07-24 13:48 ` Takashi Iwai 2003-08-11 21:30 ` Tom Watson
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.