View Single Post
Old 07-12-2012, 05:05 PM   #144
twobob
( ͡° ͜ʖ ͡°){ʇlnɐɟ ƃǝs}Týr
twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.twobob ought to be getting tired of karma fortunes by now.
 
twobob's Avatar
 
Posts: 6,586
Karma: 6299993
Join Date: Jun 2012
Location: uti gratia usura (Yao ying da ying; Mo ying da yieng)
Device: PW-WIFI|K5-3G+WIFI| K4|K3-3G|DXG|K2| Rooted Nook Touch
Initialising Alsa - the Long and Short of it.

This is a reinterpretation of the demo here:
http://equalarea.com/paul/alsa-audio.html#playex

There is a useful overview of the PCM interface that is a bit scary but not a terrible read here http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html

EDIT: Here is the Astlye compliant version of the code with additional notes and highlighting of important areas:
(In the preferred style of Knc1)
Spoiler:

Code:
#include <alsa/asoundlib.h>

main (int argc, char *argv[])
{

    // The err value being setup here would ordinarily 
    //  be populated by error handling code that is "wrapped around" 
    //  each of the calls  to the alsa methods (in bold). 

    //  I have left in one example of this construct on the snd_pcm_writei
    //  method to show how this works in practice. (At the end.)
    //  This repetitive construct is elided here for brevity, further examples
    //  can be found on previous posts on this thread
 
    // i = index for looping over buffer at the end - It's a superfluous 
    // variable used only to illustrate buffer iteration and can be ignored

    // err = alsa method return codes / frame counts etc...
    int i, err;

    // buf = An example data store to splat into buffer at the end
    // You would fill a similar construct with something 
    // useful in the real world.
    short buf[128];
 
    // Declare an instance (or occurence if you prefer)
    // of the special "Type" defined by Alsa 
    // This tells Alsa the card is an available sound device
    // We use this name to reference the device in other calls

    snd_pcm_t *playback_handle;

    // Similarly we create a new "parameters" construct
    // Simply creating the reference here is enough to create it
    // You can use this to setup the card to your liking
    // We do the bare minimum here to get us going
    snd_pcm_hw_params_t *hw_params

    // This is the 1st Alsa method we have called (directly anyway)
    // note we reference the card via it's handle we just created

    // Then we grab the first argument passed to the command line
    // argv[1] gives us this value - an e.g is below. 
    // (like ./TestProgram hw:0 would return hw:0)

    // At this stage we link the handle to the device hw:0 in this case 
    // (Further details of how devices are configed via conf files in earlier posts)

    // We would get back an error code (into the err construct) at this 
    // stage if something was amiss in accessing the card (bad conf for e.g.)

   // The full details of the enum SND_PCM_STREAM_ETC... can be
   // viewed here the complete PCM command set here

    snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0);

    // This defines some space for our params constuct
    // c is fussy about memory handling
    // Make some space - remember to tidy it up after
    // Malloc = Think "Memory Allocate"
    snd_pcm_hw_params_malloc (&hw_params);

    // This is defined in the ALSA Hardware section here
    // Fill our params space with a full configuration construct for a PCM. 
    // Making use of the space we just made and created a skeleton for us
    // Note we still reference the card via the handle from now on in
     snd_pcm_hw_params_any (playback_handle, hw_params);

    //  Restrict a configuration space to contain only one access type.   
    // The full reference for the method is here
    // I seemed to need to set this to just one type to get the card going.

    // Perhaps setting one val is absolute minimum for configuration
    // I am unsure but this got it working for me without going on to set 
    // the sample rate, access format etc. the full gory details are in the 
    // original demo, this is about getting the kindle going with minimum code

    // the full tech ref for the enum SND_PCM_ACCESS_BLAH is here
    // In essence it is pcm_read/write interleaved access 

    // Pcm means it's not done in memory it's (kinda) direct to card

    // read/write means duplexing possible, Interleaving means that we 
    // alternate samples for the left and right channel (LR,LR,LR...).

    // It's a very generic choice. You could "refine" this decision to your needs
    snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);

    // The next utility method puts our params decisions in motion 
    // "Install one PCM hardware configuration chosen from a configuration 
    // space and snd_pcm_prepare  it." say the docs here
    // so as you can see this runs another method internally for us. Happy days.
    snd_pcm_hw_params (playback_handle, hw_params);

    // This simply tidies up the memory space from the param construct 
    // as we are done with it, 

    // it's always good practice in c to destruct your disused objects. 
    snd_pcm_hw_params_free (hw_params);

    // Showtime, as shown here this "Prepare[s] PCM for use." 
    // All of these methods could have been wrapped in error handlers, 
    // only some of them have real value though, this is maybe one of them 
    snd_pcm_prepare (playback_handle);

    // We are now ready to so some stuff so let's write some interleaved data.
    // Everything after this point is "Program", we have done our job really.

    // buf is just some 0 data 128 long, 
    // 128 is length of buf, effectively buf.length
    // 10 is just a value to show looping - has no instrinsic meaning
    // write 10 * 128 shorties via the handle using interleaved writing

     // This says - in English-Psuedo-Code
     // Try to write 128 shorts to the PCM
     // If it fails a) return an error value for the process and Then 
     // b) exit the application with a code indicating Failure 
     // Do this ten times 

    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);
        }
    }

    //Tidy up. Ref here 
    snd_pcm_close (playback_handle);

    // Exit the application with a code indicating Success. 
    exit (0);
}


The Original thrust of the thread continues below.

Quote:
Originally Posted by geekmaster View Post
I also include embedded references throughout my code showing WHERE I got my ideas, to prove that they are unencumbered by patents or viral licensing. [/COLOR]
This init code is simply boiled out of an Alsa init code example, 7-ish lines (as demoed below) and you are ready to play, not bad considering the hellatiously verbose constructs of alsa.

Here is the completed basic init code: (In GM's preferred compressed style)

Spoiler:
Code:
#include <alsa/asoundlib.h>

main (int argc, char *argv[])	{

//INIT BLOCK
int err; short buf[128]; snd_pcm_t *playback_handle; 	
snd_pcm_hw_params_t *hw_params; 
snd_pcm_open (&playback_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0);
snd_pcm_hw_params_malloc (&hw_params);
snd_pcm_hw_params_any (playback_handle, hw_params);
snd_pcm_hw_params_set_access (playback_handle, hw_params, 
SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params (playback_handle, hw_params);
snd_pcm_hw_params_free (hw_params);
snd_pcm_prepare (playback_handle);
// Write something
snd_pcm_writei (playback_handle, buf, 128) ;
//Tidy up.
snd_pcm_close (playback_handle); 		exit (0);}
//Done.


The 'buf' is just to demonstrate something being pushed PCMwards. Obviously it's not required. Hacked and slashed demos. That's the best I can do with my current knowledge. See what tomorrow brings perhaps there is a quicker way. But I doubt it.

(I'll go fix the code in the post above, just in case someone tries it)

Last edited by twobob; 07-12-2012 at 08:48 PM. Reason: Made it more GM friendly - added syntax color highlighting
twobob is offline   Reply With Quote