Thread: Writing raw audio file from ALSA audio buffer

  1. #1
    Registered User
    Join Date
    Feb 2021
    Posts
    1

    Question Writing raw audio file from ALSA audio buffer

    Hello, I'm new in Linux and ALSA programming, I need to write raw audio file from ALSA audio buffer. I'm using fwrite to write raw audio data from buffer but the ouput file contain no data. Please help!
    This program is used to apply real-time audio panning from left to right and right to left
    This is the code:
    Code:
    /* %: gcc latproc.c -o latproc -lfftw3f -lasound -lrt -ldl -lm */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    #include <sched.h>
    #include <errno.h>
    #include <getopt.h>
    #include <alsa/asoundlib.h>
    #include <sys/time.h>
    #include <math.h>
    #include <math.h>
    
    
    char *pdevice = "hw:1,0";
    char *cdevice = "hw:1,0";
    snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
    int rate = 48000;
    int channels = 2;
    int buffer_size = 0;            /* auto */
    int period_size = 0;            /* auto */
    int latency_min ;           /* in frames / 2 */
    /* latency_min = 32, 64, 128,...., 1024, 2048, 8192, 16384, 32768 */
    int latency_max = 32768;         /* in frames / 2 */
    int block = 1;                  /* block mode */
    int use_poll = 0;
    int resample = 1;
    unsigned long loop_limit;
    snd_output_t *output = NULL;
    
    
    int doublecomp();
    int floatcomp();
    
    
    ///////
    
    
    double sine_array[480000];
    int last_position = 0;
    
    
    ///////
    
    
    int setparams_stream(snd_pcm_t *handle,
                 snd_pcm_hw_params_t *params,
                 const char *id)
    {
      int err;
      unsigned int rrate;
      err = snd_pcm_hw_params_any(handle, params);
      if (err < 0) {
        printf("Broken configuration for %s PCM: no configurations available: %s\n", snd_strerror(err), id);
        return err;
      }
      err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
      if (err < 0) {
        printf("Resample setup failed for %s (val %i): %s\n", id, resample, snd_strerror(err));
        return err;
      }
      err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
      if (err < 0) {
        printf("Access type not available for %s: %s\n", id, snd_strerror(err));
        return err;
      }
      err = snd_pcm_hw_params_set_format(handle, params, format);
      if (err < 0) {
        printf("Sample format not available for %s: %s\n", id, snd_strerror(err));
        return err;
      }
      err = snd_pcm_hw_params_set_channels(handle, params, channels);
      if (err < 0) {
        printf("Channels count (%i) not available for %s: %s\n", channels, id, snd_strerror(err));
        return err;
      }
      rrate = rate;
      err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
      if (err < 0) {
        printf("Rate %iHz not available for %s: %s\n", rate, id, snd_strerror(err));
        return err;
      }
      if ((int)rrate != rate) {
        printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
        return -EINVAL;
      }
      return 0;
    }
    int setparams_bufsize(snd_pcm_t *handle,
                  snd_pcm_hw_params_t *params,
                  snd_pcm_hw_params_t *tparams,
                  snd_pcm_uframes_t bufsize,
                  const char *id)
    {
      int err;
      snd_pcm_uframes_t periodsize;
      snd_pcm_hw_params_copy(params, tparams);
      periodsize = bufsize * 2;
      err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize);
      if (err < 0) {
        printf("Unable to set buffer size %li for %s: %s\n", bufsize * 2, id, snd_strerror(err));
        return err;
      }
      if (period_size > 0)
        periodsize = period_size;
      else
        periodsize /= 2;
      err = snd_pcm_hw_params_set_period_size_near(handle, params, &periodsize, 0);
      if (err < 0) {
        printf("Unable to set period size %li for %s: %s\n", periodsize, id, snd_strerror(err));
        return err;
      }
      return 0;
    }
    int setparams_set(snd_pcm_t *handle,
              snd_pcm_hw_params_t *params,
              snd_pcm_sw_params_t *swparams,
              const char *id)
    {
      int err;
      snd_pcm_uframes_t val;
      err = snd_pcm_hw_params(handle, params);
      if (err < 0) {
        printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err));
        return err;
      }
      err = snd_pcm_sw_params_current(handle, swparams);
      if (err < 0) {
        printf("Unable to determine current swparams for %s: %s\n", id, snd_strerror(err));
        return err;
      }
      err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff);
      if (err < 0) {
        printf("Unable to set start threshold mode for %s: %s\n", id, snd_strerror(err));
        return err;
      }
      if (!block)
        val = 4;
      else
        snd_pcm_hw_params_get_period_size(params, &val, NULL);
      err = snd_pcm_sw_params_set_avail_min(handle, swparams, val);
      if (err < 0) {
        printf("Unable to set avail min for %s: %s\n", id, snd_strerror(err));
        return err;
      }
      err = snd_pcm_sw_params(handle, swparams);
      if (err < 0) {
        printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err));
        return err;
      }
      return 0;
    }
    int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, int *bufsize)
    {
      int err, last_bufsize = *bufsize;
      snd_pcm_hw_params_t *pt_params, *ct_params;     /* templates with rate, format and channels */
      snd_pcm_hw_params_t *p_params, *c_params;
      snd_pcm_sw_params_t *p_swparams, *c_swparams;
      snd_pcm_uframes_t p_size, c_size, p_psize, c_psize;
      unsigned int p_time, c_time;
      unsigned int val;
      snd_pcm_hw_params_alloca(&p_params);
      snd_pcm_hw_params_alloca(&c_params);
      snd_pcm_hw_params_alloca(&pt_params);
      snd_pcm_hw_params_alloca(&ct_params);
      snd_pcm_sw_params_alloca(&p_swparams);
      snd_pcm_sw_params_alloca(&c_swparams);
      if ((err = setparams_stream(phandle, pt_params, "playback")) < 0) {
        printf("Unable to set parameters for playback stream: %s\n", snd_strerror(err));
        exit(0);
      }
      if ((err = setparams_stream(chandle, ct_params, "capture")) < 0) {
        printf("Unable to set parameters for playback stream: %s\n", snd_strerror(err));
        exit(0);
      }
      if (buffer_size > 0) {
        *bufsize = buffer_size;
        goto __set_it;
      }
     __again:
      if (buffer_size > 0)
        return -1;
      if (last_bufsize == *bufsize)
        *bufsize += 4;
      last_bufsize = *bufsize;
      if (*bufsize > latency_max)
        return -1;
     __set_it:
      if ((err = setparams_bufsize(phandle, p_params, pt_params, *bufsize, "playback")) < 0) {
        printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
        exit(0);
      }
      if ((err = setparams_bufsize(chandle, c_params, ct_params, *bufsize, "capture")) < 0) {
        printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
        exit(0);
      }
      snd_pcm_hw_params_get_period_size(p_params, &p_psize, NULL);
      if (p_psize > (unsigned int)*bufsize)
        *bufsize = p_psize;
      snd_pcm_hw_params_get_period_size(c_params, &c_psize, NULL);
      if (c_psize > (unsigned int)*bufsize)
        *bufsize = c_psize;
      snd_pcm_hw_params_get_period_time(p_params, &p_time, NULL);
      snd_pcm_hw_params_get_period_time(c_params, &c_time, NULL);
      if (p_time != c_time)
        goto __again;
      snd_pcm_hw_params_get_buffer_size(p_params, &p_size);
      if (p_psize * 2 < p_size) {
        snd_pcm_hw_params_get_periods_min(p_params, &val, NULL);
        if (val > 2) {
          printf("playback device does not support 2 periods per buffer\n");
          exit(0);
        }
        goto __again;
      }
      snd_pcm_hw_params_get_buffer_size(c_params, &c_size);
      if (c_psize * 2 < c_size) {
        snd_pcm_hw_params_get_periods_min(c_params, &val, NULL);
        if (val > 2 ) {
          printf("capture device does not support 2 periods per buffer\n");
          exit(0);
        }
        goto __again;
      }
      if ((err = setparams_set(phandle, p_params, p_swparams, "playback")) < 0) {
        printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
        exit(0);
      }
      if ((err = setparams_set(chandle, c_params, c_swparams, "capture")) < 0) {
        printf("Unable to set sw parameters for playback stream: %s\n", snd_strerror(err));
        exit(0);
      }
      if ((err = snd_pcm_prepare(phandle)) < 0) {
        printf("Prepare error: %s\n", snd_strerror(err));
        exit(0);
      }
      snd_pcm_dump(phandle, output);
      snd_pcm_dump(chandle, output);
      fflush(stdout);
      return 0;
    }
    
    
    long readbuf(snd_pcm_t *handle, short *buf, long len, size_t *frames, size_t *max)
    {
      long r=0,hitung=0;
    
    
        int frame_bytes = (snd_pcm_format_width(format) / 8) * channels;
        do {
        printf("hitung= %ld; len= %ld; r= %ld\n",hitung++,len,r);
          r = snd_pcm_readi(handle, buf, len);
          if (r > 0) {
        buf += r * frame_bytes;
        len -= r;
        *frames += r;
        if ((long)*max < r)
          *max = r;
    
    
          }
        printf("hitung= %ld; len= %ld; r= %ld\n",hitung++,len,r);
    
    
    
    
        } while (r >= 1 && len > 0);
    
    
    
    
       return r;
    }
    
    
    long writebuf(snd_pcm_t *handle, short *buf, long len, size_t *frames)
    {
      long r;
      while (len > 0) {
        r = snd_pcm_writei(handle, buf, len);
        if (r == -EAGAIN)
          continue;
        if (r < 0)
          return r;
        buf += r * 4;
        len -= r;
        *frames += r;
      }
      return 0;
    }
    
    
    
    
    void pan_v2(short *buffer, int r, double a) {
      int i;
      int latency_max = 32768;
      int buflen=latency_max/32;        //default: 32 for latency 512
      double depth = 1.0, xbuf;
      double LVOL = 0;
      double RVOL = 0;
    
    
      LVOL = 1-a; //Modulator signal value 0 = center panning
      RVOL = 1+a; //Modulator signal value 0 = center panning
    
    
      for (i=0;i<buflen;i++)    {
    
    
          if(i%2==0)     /* Left channel */ {
          xbuf= (double)buffer[i]*(double)(LVOL);
          buffer[i]=(int16_t)(xbuf);
        }
          else          /* Right channel */ {
          xbuf= (double)buffer[i]*(double)(RVOL);
          buffer[i]=(int16_t)(xbuf);
        }
      }
    }
    
    
    
    
    int main()
    {
          snd_pcm_t *phandle, *chandle;
          short *buffer;
          int err, latency, morehelp;
          snd_timestamp_t p_tstamp, c_tstamp;
          ssize_t r;
          size_t frames_in, frames_out, in_max;
          int effect = 0;
          morehelp = 0;
    
    
    //////////////////////////////////////////////// Generating the Sine Array
    double target_frequency = 0.5; //Target Frequency
    double converted_frequency = 250.0*target_frequency; //for some reason 1 Hz = 250
    double dpi;
    int sampling_rate = 48000.0;
    double pi = M_PI;
    double temp_value = 0;
    dpi = (2.0*pi)*(converted_frequency/sampling_rate);
    for(int i=i;i<48000;i++) {
        temp_value = (double)sin(dpi*(double)i);
        sine_array[i] = (double)temp_value;
    }
    //////////////////////////////////////////////////////////////////////////
      printf("\n\n");
      printf(
         "Tip #1 (usable latency with large periods, non-blocking mode, good CPU usage,\n"
         "        superb xrun prevention):\n"
         "  latency -m 8192 -M 8192 -t 1 -p\n"
         "Tip #2 (superb latency, non-blocking mode, but heavy CPU usage):\n"
         "  latency -m 128 -M 128\n"
         );
    
    
      printf("\n");
      latency_min = 512; //Fixed latency setting
    
    
          err = snd_output_stdio_attach(&output, stdout, 0);
          if (err < 0) {
            printf("Output failed: %s\n", snd_strerror(err));
            return 0;
          }
    
    
          latency = latency_min - 4;
    
    
          /*--------------------------------- penting ----------------------*/
          buffer = malloc((latency_max * snd_pcm_format_width(format) / 8) * 2);
          /*----------------------------------------------------------------*/
    
    
          printf("Playback device is %s\n", pdevice);
          printf("Capture device is %s\n", cdevice);
          printf("Parameters are %iHz, %s, %i channels, %s mode\n",
             rate, snd_pcm_format_name(format), channels, block ? "blocking" : "non-blocking");
          printf("Poll mode: %s\n", use_poll ? "yes" : "no");
    
    
          if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK)) < 0) {
            printf("Playback open error: %s\n", snd_strerror(err));
            return 0;
          }
          if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE, block ? 0 : SND_PCM_NONBLOCK)) < 0) {
            printf("Record open error: %s\n", snd_strerror(err));
            return 0;
          }
    
    
          while (1) {
            frames_in = frames_out = 0;
            if (setparams(phandle, chandle, &latency) < 0)
              break;
            if ((err = snd_pcm_link(chandle, phandle)) < 0) {
              printf("Streams link error: %s\n", snd_strerror(err));
              exit(0);
            }
            if (snd_pcm_format_set_silence(format, buffer, latency*channels) < 0) {
              fprintf(stderr, "silence error\n");
              break;
            }
            if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
              fprintf(stderr, "write error\n");
              break;
            }
            if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
              fprintf(stderr, "write error\n");
              break;
            }
            if ((err = snd_pcm_start(chandle)) < 0) {
              printf("Go error: %s\n", snd_strerror(err));
              exit(0);
            }
            in_max = 0;
    
    
            int lp = 0;
            double a = 0;
            double depth = 1.0;
    
    
            short audio_buffer_out[480000] = {0};
            FILE *f;
    
    
            while (1) {
              r = readbuf(chandle, buffer, latency, &frames_in, &in_max);  /* capture audio from mic */
              a = sine_array[lp];
              pan_v2(buffer,r,a); //Apply Panning
              audio_buffer_out[lp] = buffer; //Save data from ALSA buffer
              writebuf(phandle, buffer, r, &frames_out); //output panned audio from ALSA buffer
              if(lp == 1000) {
                printf("\nWriting to raw file\n");
                f = fopen("./pan_output.raw","wb");
                  if(f==NULL) {
                    printf("\nfile error\n");
                    exit(1);
                  }
                fwrite(&audio_buffer_out,sizeof(short),1,f);
                fclose(f);
                printf("Done\n");
                exit(0);
              }
              lp++; //Modulator Signal Array Index
              printf("Sine Array Index: %d\n",lp);
    
    
            }
          printf("Hardware sync\n");
          snd_pcm_drop(chandle);
          snd_pcm_nonblock(phandle, 0);
          snd_pcm_drain(phandle);
          snd_pcm_nonblock(phandle, !block ? 1 : 0);
    
    
          snd_pcm_unlink(chandle);
          snd_pcm_hw_free(phandle);
          snd_pcm_hw_free(chandle);
          }
          snd_pcm_close(phandle);
          snd_pcm_close(chandle);
          return 0;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,626
    Yeah, 500 lines of poorly formatted code containing goto's is not a good start.

    You have a lot of printf's in there, perhaps you could post those as well.
    Bear in mind that either we can't run your code at all (or are generally too busy), it's up to you to be as detailed as possible.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 09-08-2017, 07:53 PM
  2. Writing audio to file
    By Gelby in forum C Programming
    Replies: 5
    Last Post: 08-28-2016, 09:54 AM
  3. Audio File
    By IceBall in forum Tech Board
    Replies: 4
    Last Post: 08-14-2003, 10:36 AM
  4. Audio CD File Extension
    By sean in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 02-17-2003, 10:47 PM
  5. Playing an Audio Wav File
    By Robert_Ingleby in forum C++ Programming
    Replies: 2
    Last Post: 12-02-2001, 06:29 PM

Tags for this Thread