Difference between revisions of "Упражнение 7. Аудио контролер"

From Ilianko
 
Line 1: Line 1:
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#include <alsa/asoundlib.h>
 +
     
 +
int main (int argc, char *argv[])
 +
{
 +
  /* 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 *pcm_name;
 +
 
 +
  /* Init pcm_name. Of course, later you */
 +
    /* will make this configurable ;-)    */
 +
  pcm_name = strdup("default");
 +
 
 +
    /* 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) {
 +
      fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
 +
      return(-1);
 +
    }
 +
   
 +
   
 +
    /* Init hwparams with full configuration space */
 +
    if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
 +
      fprintf(stderr, "Can not configure this PCM device.\n");
 +
      return(-1);
 +
    }
 +
   
 +
   
 +
   
 +
   
 +
   
 +
    unsigned int rate = 44100; /* Sample rate */
 +
    unsigned 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 = 2;      /* Number of periods */
 +
    snd_pcm_uframes_t periodsize = 512; /* Periodsize (bytes) */
 +
   
 +
    /* Set sample format */
 +
    if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
 +
      fprintf(stderr, "Error setting format.\n");
 +
      return(-1);
 +
    }
 +
   
 +
    /* Set sample rate. If the exact rate is not supported */
 +
    /* by the hardware, use nearest possible rate.        */
 +
    exact_rate = rate;
 +
   
 +
    if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0) {
 +
      fprintf(stderr, "Error setting rate.\n");
 +
      return(-1);
 +
    }
 +
   
 +
    if (rate != exact_rate) {
 +
      fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n ==> Using %d Hz instead.\n", rate, exact_rate);
 +
    }
 +
   
 +
    /* Set number of channels */
 +
    if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) {
 +
      fprintf(stderr, "Error setting channels.\n");
 +
      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) {
 +
      fprintf(stderr, "Error setting periods.\n");
 +
      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) {
 +
      fprintf(stderr, "Error setting buffersize.\n");
 +
      return(-1);
 +
    }
 +
   
 +
    /* Apply HW parameter settings to */
 +
    /* PCM device and prepare device  */
 +
    if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) {
 +
      fprintf(stderr, "Error setting HW params.\n");
 +
      return(-1);
 +
    }
 +
   
 +
   
 +
    /* Write num_frames frames from buffer data to    */
 +
    /* the PCM device pointed to by pcm_handle.      */
 +
    /* Returns the number of frames actually written. */
 +
    //  snd_pcm_sframes_t snd_pcm_writei(pcm_handle, data, num_frames);
 +
   
 +
    unsigned char *data;
 +
    int pcmreturn, l1, l2;
 +
    short s1, s2, s3, s4;
 +
    int frames;
 +
  //  int num_frames= 100;
 +
 +
    data = (unsigned char *)malloc(periodsize);
 +
    frames = periodsize >> 3;
 +
    for(l1 = 0; l1 < 10000; l1++) {
 +
     
 +
      for(l2 = 0; l2 < frames; l2++) {
 +
       
 +
        s1 = (l2 % 64)  * 100 - 5000; 
 +
        s2 = (l2 % 128) * 100 - 5000;
 +
        s3 = (l2 % 192) * 100 - 5000; 
 +
        s4 = (l2 % 256) * 100 - 5000;   
 +
       
 +
        data[8*l2] = (unsigned char)s1;
 +
        data[8*l2+1] = s1 >> 8;
 +
        data[8*l2+2] = (unsigned char)s2;
 +
        data[8*l2+3] = s2 >> 8;
 +
       
 +
        data[8*l2+4] = (unsigned char)s4;
 +
        data[8*l2+5] = s3 >> 8;
 +
        data[8*l2+6] = (unsigned char)s3;
 +
        data[8*l2+7] = s4 >> 8;
 +
     
 +
      }
 +
      while ((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0) {
 +
        snd_pcm_prepare(pcm_handle);
 +
        fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
 +
      }
 +
    }
 +
    /*
 +
   
 +
    unsigned char *data;
 +
    int pcmreturn, l1, l2;
 +
    short s1, s2;
 +
    int frames;
 +
 +
    data = (unsigned char *)malloc(periodsize);
 +
    frames = periodsize >> 2;
 +
    for(l1 = 0; l1 < 10000; l1++) {
 +
      for(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) {
 +
        snd_pcm_prepare(pcm_handle);
 +
        fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
 +
      }
 +
    }*/
 +
  return 0;
 +
}
 +
  
  
 
[[Category:Компютърна периферия]]
 
[[Category:Компютърна периферия]]

Revision as of 13:47, 26 April 2011

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <alsa/asoundlib.h>

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

 /* 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 *pcm_name;
 
 /* Init pcm_name. Of course, later you */
   /* will make this configurable ;-)     */
  pcm_name = strdup("default");
 
   /* 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) {
     fprintf(stderr, "Error opening PCM device %s\n", pcm_name);
     return(-1);
   }
   
   
   /* Init hwparams with full configuration space */
   if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
     fprintf(stderr, "Can not configure this PCM device.\n");
     return(-1);
   }
   
   
   
   
   
   unsigned int rate = 44100; /* Sample rate */
   unsigned 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 = 2;       /* Number of periods */
   snd_pcm_uframes_t periodsize = 512; /* Periodsize (bytes) */
   
    /* Set sample format */
   if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) {
     fprintf(stderr, "Error setting format.\n");
     return(-1);
   }
   
   /* Set sample rate. If the exact rate is not supported */
   /* by the hardware, use nearest possible rate.         */ 
   exact_rate = rate;
   
   if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0) {
     fprintf(stderr, "Error setting rate.\n");
     return(-1);
   }
   
   if (rate != exact_rate) {
     fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n ==> Using %d Hz instead.\n", rate, exact_rate);
   }
   
    /* Set number of channels */
   if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) {
     fprintf(stderr, "Error setting channels.\n");
     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) {
     fprintf(stderr, "Error setting periods.\n");
     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) {
     fprintf(stderr, "Error setting buffersize.\n");
     return(-1);
   }
   
    /* Apply HW parameter settings to */
   /* PCM device and prepare device  */
   if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) {
     fprintf(stderr, "Error setting HW params.\n");
     return(-1);
   }
   
   
   /* Write num_frames frames from buffer data to    */ 
   /* the PCM device pointed to by pcm_handle.       */
   /* Returns the number of frames actually written. */
   //  snd_pcm_sframes_t snd_pcm_writei(pcm_handle, data, num_frames);
   
   unsigned char *data;
   int pcmreturn, l1, l2;
   short s1, s2, s3, s4;
   int frames;
 //  int num_frames= 100;
   data = (unsigned char *)malloc(periodsize);
   frames = periodsize >> 3;
   for(l1 = 0; l1 < 10000; l1++) {
     
     for(l2 = 0; l2 < frames; l2++) {
       
       s1 = (l2 % 64)  * 100 - 5000;  
       s2 = (l2 % 128) * 100 - 5000;
       s3 = (l2 % 192) * 100 - 5000;  
       s4 = (l2 % 256) * 100 - 5000;    
       
       data[8*l2] = (unsigned char)s1;
       data[8*l2+1] = s1 >> 8;
       data[8*l2+2] = (unsigned char)s2;
       data[8*l2+3] = s2 >> 8;
       
       data[8*l2+4] = (unsigned char)s4;
       data[8*l2+5] = s3 >> 8;
       data[8*l2+6] = (unsigned char)s3;
       data[8*l2+7] = s4 >> 8;
     
     }
     while ((pcmreturn = snd_pcm_writei(pcm_handle, data, frames)) < 0) {
       snd_pcm_prepare(pcm_handle);
       fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
     }
   }
   /*
   
    unsigned char *data;
   int pcmreturn, l1, l2;
   short s1, s2;
   int frames;
   data = (unsigned char *)malloc(periodsize);
   frames = periodsize >> 2;
   for(l1 = 0; l1 < 10000; l1++) {
     for(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) {
       snd_pcm_prepare(pcm_handle);
       fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n");
     }
   }*/
 return 0;

}