Example #1
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 size, p_size, c_size, p_psize, c_psize;
	unsigned int p_time, c_time;

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

      __again:
      	if (last_bufsize == *bufsize)
		*bufsize += 4;
	last_bufsize = *bufsize;
	if (*bufsize > latency_max)
		return -1;
	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, &size, NULL);
	if (size > *bufsize)
		*bufsize = size;
	snd_pcm_hw_params_get_period_size(c_params, &size, NULL);
	if (size > *bufsize)
		*bufsize = size;
	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_period_size(p_params, &p_psize, NULL);
	snd_pcm_hw_params_get_buffer_size(p_params, &p_size);
	if (p_psize * 2 < p_size)
		goto __again;
	snd_pcm_hw_params_get_period_size(c_params, &c_psize, NULL);
	snd_pcm_hw_params_get_buffer_size(c_params, &c_size);
	if (c_psize * 2 < c_size)
		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;
}
Example #2
0
int VoiceStreamer::setparams_c(snd_pcm_t *chandle, int *bufsize) {
   int err, last_bufsize = *bufsize;
   snd_pcm_hw_params_t *ct_params; // templates w/ rate, format and channels
   snd_pcm_hw_params_t *c_params;
   snd_pcm_sw_params_t *c_swparams;
   snd_pcm_uframes_t c_size, c_psize;
   unsigned int val;

   snd_pcm_hw_params_alloca(&c_params);
   snd_pcm_hw_params_alloca(&ct_params);
   snd_pcm_sw_params_alloca(&c_swparams);
   if((err = setparams_stream(chandle, ct_params, "capture")) < 0) {
      printf("Unable to set parameters for capture stream: %s\n", 
            snd_strerror(err));
      exit(EXIT_FAILURE);
   }

   bool again = true;
   if (buffer_size > 0) {
      *bufsize = buffer_size;
      again = false;
   }

   for (;; again = true) {
      if (again) {
         if (buffer_size > 0)
            return -1;
         if (last_bufsize == *bufsize)
            *bufsize +=4;
         last_bufsize = *bufsize;
         if (*bufsize > latency_max)
            return -1;
      }
      if ((err = setparams_bufsize(chandle, c_params, ct_params, *bufsize,
                  "capture")) < 0) {
         printf("Unable to set sw parameters for capture stream: %s\n",
               snd_strerror(err));
         exit(EXIT_FAILURE);
      }

      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_buffer_size(c_params, &c_size);
      if (c_psize*4 < c_size) {
         snd_pcm_hw_params_get_periods_min(c_params, &val, NULL);
         if (val > 4) {
            printf("Capture device does not support 4 periods per buffer\n");
            exit(EXIT_FAILURE);
         }
         continue;
      }
      
      break;
   }

   if ((err = setparams_set(chandle, c_params, c_swparams, "capture")) < 0) {
      printf("Unable to set sw parameters for capture stream: %s\n", 
            snd_strerror(err));
      exit(EXIT_FAILURE);
   }

   fflush(stdout);
   return 0;
}
Example #3
0
static int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle,
                     snd_pcm_format_t format,
                     int latency, int allow_resample,
                     struct final_params *negotiated)
{
    int i;
    unsigned ratep, ratec = 0;
    unsigned ratemin = 32000, ratemax = 96000, val;
    int err, channels = 2;
    snd_pcm_hw_params_t *p_hwparams, *c_hwparams;
    snd_pcm_sw_params_t *p_swparams, *c_swparams;
    snd_pcm_uframes_t c_size, p_psize, c_psize;
    /* Our latency is 2 periods (in usecs) */
    unsigned int c_periods = 2, p_periods;
    unsigned int c_periodtime, p_periodtime;
    const unsigned int prefered_rates[] = { 44100, 48000, 32000 };

    snd_pcm_hw_params_alloca(&p_hwparams);
    snd_pcm_hw_params_alloca(&c_hwparams);
    snd_pcm_sw_params_alloca(&p_swparams);
    snd_pcm_sw_params_alloca(&c_swparams);

    if (setparams_stream(chandle, c_hwparams, format, &channels, "capture"))
        return 1;

    if (setparams_stream(phandle, p_hwparams, format, &channels, "playback"))
        return 1;

    if (allow_resample) {
        err = snd_pcm_hw_params_set_rate_resample(chandle, c_hwparams, 1);
        if (err < 0) {
            fprintf(error_fp, "alsa: Resample setup failed: %s\n", snd_strerror(err));
            return 1;
        } else if (verbose)
            fprintf(error_fp, "alsa: Resample enabled.\n");
    }

    err = snd_pcm_hw_params_get_rate_min(c_hwparams, &ratemin, 0);
    if (err >= 0 && verbose)
        fprintf(error_fp, "alsa: Capture min rate is %d\n", ratemin);
    err = snd_pcm_hw_params_get_rate_max(c_hwparams, &ratemax, 0);
    if (err >= 0 && verbose)
        fprintf(error_fp, "alsa: Capture max rate is %u\n", ratemax);

    err = snd_pcm_hw_params_get_rate_min(p_hwparams, &val, 0);
    if (err >= 0) {
        if (verbose)
            fprintf(error_fp, "alsa: Playback min rate is %u\n", val);
        if (val > ratemin)
            ratemin = val;
    }
    err = snd_pcm_hw_params_get_rate_max(p_hwparams, &val, 0);
    if (err >= 0) {
        if (verbose)
            fprintf(error_fp, "alsa: Playback max rate is %u\n", val);
        if (val < ratemax)
            ratemax = val;
    }

    if (verbose)
        fprintf(error_fp,
                "alsa: Will search a common rate between %u and %u\n",
                ratemin, ratemax);

    /* First try a set of common rates */
    err = -1;
    for (i = 0; i < ARRAY_SIZE(prefered_rates); i++) {
        if (prefered_rates[i] < ratemin || prefered_rates[i] > ratemax)
            continue;
        ratep = ratec = prefered_rates[i];
        err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
                            allow_resample, &ratep, &ratec);
        if (err == 0)
            break;
    }

    if (err != 0) {
        if (ratemin >= 44100) {
            for (i = ratemin; i <= ratemax; i += 100) {
                ratep = ratec = i;
                err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
                                    allow_resample, &ratep, &ratec);
                if (err == 0)
                    break;
            }
        } else {
            for (i = ratemax; i >= ratemin; i -= 100) {
                ratep = ratec = i;
                err = alsa_try_rate(phandle, chandle, p_hwparams, c_hwparams,
                                    allow_resample, &ratep, &ratec);
                if (err == 0)
                    break;
            }
        }
    }

    if (err < 0) {
        fprintf(error_fp, "alsa: Failed to set a supported rate: %s\n",
                snd_strerror(err));
        return 1;
    }
    if (ratep != ratec) {
        if (verbose || allow_resample)
            fprintf(error_fp,
                    "alsa: Couldn't find a rate that it is supported by both playback and capture\n");
        return 2;
    }
    if (verbose)
        fprintf(error_fp, "alsa: Using Rate %d\n", ratec);

    /* Negotiate period parameters */

    c_periodtime = latency * 1000 / c_periods;
    getparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture");
    p_periods = c_periods * 2;
    p_periodtime = c_periodtime;
    getparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback");
    c_periods = p_periods / 2;

    /*
     * Some playback devices support a very limited periodtime range. If the user needs to
     * use a higher latency to avoid overrun/underrun, use an alternate algorithm of incresing
     * the number of periods, to archive the needed latency
     */
    if (p_periodtime < c_periodtime) {
        c_periodtime = p_periodtime;
        c_periods = round (latency * 1000.0 / c_periodtime + 0.5);
        getparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture");
        p_periods = c_periods * 2;
        p_periodtime = c_periodtime;
        getparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback");
        c_periods = p_periods / 2;
    }

    if (setparams_periods(chandle, c_hwparams, &c_periodtime, &c_periods, "capture"))
        return 1;

    /* Note we use twice as much periods for the playback buffer, since we
       will get a period size near the requested time and we don't want it to
       end up smaller then the capture buffer as then we could end up blocking
       on writing to it. Note we will configure the playback dev to start
       playing as soon as it has 2 capture periods worth of data, so this
       won't influence latency */
    if (setparams_periods(phandle, p_hwparams, &p_periodtime, &p_periods, "playback"))
        return 1;

    snd_pcm_hw_params_get_period_size(p_hwparams, &p_psize, NULL);
    snd_pcm_hw_params_get_period_size(c_hwparams, &c_psize, NULL);
    snd_pcm_hw_params_get_buffer_size(c_hwparams, &c_size);

    latency = c_periods * c_psize;
    if (setparams_set(phandle, p_hwparams, p_swparams, latency, "playback"))
        return 1;

    if (setparams_set(chandle, c_hwparams, c_swparams, c_psize, "capture"))
        return 1;

    if ((err = snd_pcm_prepare(phandle)) < 0) {
        fprintf(error_fp, "alsa: Prepare error: %s\n", snd_strerror(err));
        return 1;
    }

    if (verbose) {
        fprintf(error_fp, "alsa: Negociated configuration:\n");
        snd_pcm_dump_setup(phandle, output);
        snd_pcm_dump_setup(chandle, output);
        fprintf(error_fp, "alsa: Parameters are %iHz, %s, %i channels\n",
                ratep, snd_pcm_format_name(format), channels);
        fprintf(error_fp, "alsa: Set bitrate to %u%s, buffer size is %u\n", ratec,
                allow_resample ? " with resample enabled at playback": "",
                (unsigned int)c_size);
    }

    negotiated->bufsize = c_size;
    negotiated->rate = ratep;
    negotiated->channels = channels;
    negotiated->latency = latency;
    return 0;
}
Example #4
0
int VoiceStreamer::setparams_p(snd_pcm_t *phandle, int *bufsize) {
   int err, last_bufsize = *bufsize;
   snd_pcm_hw_params_t *pt_params;
   snd_pcm_hw_params_t *p_params;
   snd_pcm_sw_params_t *p_swparams;
   snd_pcm_uframes_t p_size, p_psize;
   unsigned int val;

   snd_pcm_hw_params_alloca(&p_params);
   snd_pcm_hw_params_alloca(&pt_params);
   snd_pcm_sw_params_alloca(&p_swparams);
   if ((err = setparams_stream(phandle, pt_params, "playback")) < 0) {
      printf("Unable to set parameters for playback stream: %s\n",
            snd_strerror(err));
      exit(EXIT_FAILURE);
   }

   bool again = true;
   if (buffer_size > 0) {
      *bufsize = buffer_size;
      again = false;
   }

   for (;; again = true) {
      if (again) {
         if (buffer_size > 0)
            return -1;
         if (last_bufsize == *bufsize)
            *bufsize +=4;
         last_bufsize = *bufsize;
         if (*bufsize > latency_max)
            return -1;
      }
      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(EXIT_FAILURE);
      }

      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_buffer_size(p_params, &p_size);
      if (p_psize*4 < p_size) {
         snd_pcm_hw_params_get_periods_min(p_params, &val, NULL);
         if (val > 4) {
            printf("Playback device does not support 4 periods per buffer\n");
            exit(EXIT_FAILURE);
         }
         continue;
      }
      
      break;
   }

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

   fflush(stdout);
   return 0;

}