コード例 #1
0
    optional<int> AudioOutputDeviceAlsa::ParameterChannels::RangeMinAsInt(std::map<String,String> Parameters) {
        uint channels = 1;
        if (!Parameters.count("CARD")) return channels;

        // obtain information from given sound card
        ParameterCard card(Parameters["CARD"]);
        String pcm_name = "hw:" + card.ValueAsString();
        snd_pcm_t* pcm_handle = NULL;
        if (snd_pcm_open(&pcm_handle, pcm_name.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0) return channels;
        snd_pcm_hw_params_t* hwparams;
        snd_pcm_hw_params_alloca(&hwparams);
        if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
            snd_pcm_close(pcm_handle);
            return channels;
        }

        if (snd_pcm_hw_params_get_channels_min(hwparams, &channels) < 0) {
            snd_pcm_close(pcm_handle);
            return channels;
        }
        snd_pcm_close(pcm_handle);
        return channels;
    }
コード例 #2
0
size_t stack_alsa_audio_device_list_outputs(StackAudioDeviceDesc **outputs)
{
	static const int common_sample_rates[] = {8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000};
	static const size_t num_common_sample_rates = 11;

	// Initialise pulse audio
	if (!stack_init_alsa_audio())
	{
		// Failed to initialise, return NULL
		*outputs = NULL;
		return 0;	
	}

	// Get some hints	
	void **hints = NULL;
	int result = snd_device_name_hint(-1, "pcm", &hints);
	if (result != 0)
	{
		*outputs = NULL;
		return 0;
	}

	size_t alsa_device_count = 0, stack_device_count = 0;

	// Count how many devices we find
	for (size_t i = 0; hints[i] != NULL; i++)
	{
		alsa_device_count = i + 1;
	}

	// If there are no devices, return immediately
	if (alsa_device_count == 0)
	{
		snd_device_name_free_hint(hints);
		*outputs = NULL;
		return 0;
	}

	StackAudioDeviceDesc* devices = new StackAudioDeviceDesc[alsa_device_count];

	// Iterate over the devices and build information
	for (size_t alsa_device_idx = 0, stack_device_idx = 0; alsa_device_idx < alsa_device_count; alsa_device_idx++)
	{
		char *name = snd_device_name_get_hint(hints[alsa_device_idx], "NAME");
		char *desc = snd_device_name_get_hint(hints[alsa_device_idx], "DESC");

		// Open the device
		snd_pcm_t* pcm = NULL;
		if (snd_pcm_open(&pcm, name, SND_PCM_STREAM_PLAYBACK, 0) != 0)
		{
			free(name);
			free(desc);
			continue;
		}

		// Get parameters
		snd_pcm_hw_params_t* hw_params = NULL;
		snd_pcm_hw_params_malloc(&hw_params);
		snd_pcm_hw_params_any(pcm, hw_params);

		// Get minimum and maximum number of channels
		unsigned int min, max;
		snd_pcm_hw_params_get_channels_min(hw_params, &min);
		snd_pcm_hw_params_get_channels_max(hw_params, &max);

		// Limit the maximum to 32 channels, as some devices return "-1" channels
		if (max > 32)
		{
			max = 32;
		}

		// Store channel counts
		devices[stack_device_idx].min_channels = min;
		devices[stack_device_idx].max_channels = max;

		// Get minimum and maximum sample rates
		int dir;
		snd_pcm_hw_params_get_rate_min(hw_params, &min, &dir);
		snd_pcm_hw_params_get_rate_max(hw_params, &max, &dir);

		// Iterate over our common sample rates and see which ones are valid
		size_t sample_rate_count = 0;
		for (size_t common_rate_idx = 0; common_rate_idx < num_common_sample_rates; common_rate_idx++)
		{
			if (common_sample_rates[common_rate_idx] >= min && common_sample_rates[common_rate_idx] <= max)
			{
				if (snd_pcm_hw_params_test_rate(pcm, hw_params, common_sample_rates[common_rate_idx], 0) == 0)
				{
					sample_rate_count++;
				}
			}
		}

		// Store the sample rates
		devices[stack_device_idx].num_rates = sample_rate_count;
		if (sample_rate_count > 0)
		{
			devices[stack_device_idx].rates = new uint32_t[sample_rate_count];
			for (size_t rate_idx = 0, common_rate_idx = 0; common_rate_idx < num_common_sample_rates; common_rate_idx++)
			{
				if (common_sample_rates[common_rate_idx] >= min && common_sample_rates[common_rate_idx] <= max)
				{
					devices[stack_device_idx].rates[rate_idx] = common_sample_rates[common_rate_idx];
					rate_idx++;
				}
			}

		}
		else
		{
			devices[stack_device_idx].rates = NULL;
		}

		// Store the name and description
		devices[stack_device_idx].name = strdup(name);
		devices[stack_device_idx].desc = strdup(desc);

		// Tidy up
		free(name);
		free(desc);
		snd_pcm_hw_params_free(hw_params);
		snd_pcm_close(pcm);
		stack_device_count++;
		stack_device_idx++;
	}

	// Tidy up
	snd_device_name_free_hint(hints);

	// We can technically return an array that contains more elements than
	// we say (if a device fails to open, for example), but this is not a 
	// problem, as we only allocate and indeed free the internals of the
	// number we say, but we tidy up the whole array
	*outputs = devices;
	return stack_device_count;
}
void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
    snd_pcm_t* handle;
    snd_pcm_format_mask_t* formatMask;
    snd_pcm_format_t format;
    snd_pcm_hw_params_t* hwParams;
    int handledBits[MAX_BIT_INDEX+1];

    int ret;
    int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc;
    int origSampleSizeInBytes, origSignificantBits;
    int channels, minChannels, maxChannels;
    int rate, bitIndex;

    for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE;
    if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) {
        return;
    }
    ret = snd_pcm_format_mask_malloc(&formatMask);
    if (ret != 0) {
        ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret);
    } else {
        ret = snd_pcm_hw_params_malloc(&hwParams);
        if (ret != 0) {
            ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
        } else {
            ret = snd_pcm_hw_params_any(handle, hwParams);
            if (ret != 0) {
                ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
            }
        }
        snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
#ifdef ALSA_PCM_NEW_HW_PARAMS_API
        if (ret == 0) {
            ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels);
            if (ret != 0) {
                ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret);
            }
        }
        if (ret == 0) {
            ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels);
            if (ret != 0) {
                ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret);
            }
        }
#else
        minChannels = snd_pcm_hw_params_get_channels_min(hwParams);
        maxChannels = snd_pcm_hw_params_get_channels_max(hwParams);
        if (minChannels > maxChannels) {
            ERROR2("MinChannels=%d, maxChannels=%d\n", minChannels, maxChannels);
        }
#endif

        // since we queried the hw: device, for many soundcards, it will only
        // report the maximum number of channels (which is the only way to talk
        // to the hw: device). Since we will, however, open the plughw: device
        // when opening the Source/TargetDataLine, we can safely assume that
        // also the channels 1..maxChannels are available.
#ifdef ALSA_PCM_USE_PLUGHW
        minChannels = 1;
#endif
        if (ret == 0) {
            // plughw: supports any sample rate
            rate = -1;
            for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
                if (snd_pcm_format_mask_test(formatMask, format)) {
                    // format exists
                    if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes,
                                                &origSignificantBits,
                                                &isSigned, &isBigEndian, &enc)) {
                        // now if we use plughw:, we can use any bit size below the
                        // natively supported ones. Some ALSA drivers only support the maximum
                        // bit size, so we add any sample rates below the reported one.
                        // E.g. this iteration reports support for 16-bit.
                        // getBitIndex will return 2, so it will add entries for
                        // 16-bit (bitIndex=2) and in the next do-while loop iteration,
                        // it will decrease bitIndex and will therefore add 8-bit support.
                        bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits);
                        do {
                            if (bitIndex == 0
                                || bitIndex == MAX_BIT_INDEX
                                || !handledBits[bitIndex]) {
                                handledBits[bitIndex] = TRUE;
                                sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes);
                                significantBits = getSignificantBits(bitIndex, origSignificantBits);
                                if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) {
                                    // avoid too many channels explicitly listed
                                    // just add -1, min, and max
                                    DAUDIO_AddAudioFormat(creator, significantBits,
                                                          -1, -1, rate,
                                                          enc, isSigned, isBigEndian);
                                    DAUDIO_AddAudioFormat(creator, significantBits,
                                                          sampleSizeInBytes * minChannels,
                                                          minChannels, rate,
                                                          enc, isSigned, isBigEndian);
                                    DAUDIO_AddAudioFormat(creator, significantBits,
                                                          sampleSizeInBytes * maxChannels,
                                                          maxChannels, rate,
                                                          enc, isSigned, isBigEndian);
                                } else {
                                    for (channels = minChannels; channels <= maxChannels; channels++) {
                                        DAUDIO_AddAudioFormat(creator, significantBits,
                                                              (channels < 0)?-1:(sampleSizeInBytes * channels),
                                                              channels, rate,
                                                              enc, isSigned, isBigEndian);
                                    }
                                }
                            }
#ifndef ALSA_PCM_USE_PLUGHW
                            // without plugin, do not add fake formats
                            break;
#endif
                        } while (--bitIndex > 0);
                    } else {
                        TRACE1("could not get format from alsa for format %d\n", format);
                    }
                } else {
                    //TRACE1("Format %d not supported\n", format);
                }
            } // for loop
            snd_pcm_hw_params_free(hwParams);
        }
        snd_pcm_format_mask_free(formatMask);
    }
    snd_pcm_close(handle);
}
コード例 #4
0
/**
 * ags_devout_pcm_info:
 * @soundcard: the #AgsSoundcard
 * @card_id: alsa identifier
 * @channels_min: minimum channels supported
 * @channels_max: maximum channels supported
 * @rate_min: minimum samplerate supported
 * @rate_max: maximum samplerate supported
 * @buffer_size_min: minimum buffer size supported
 * @buffer_size_max maximum buffer size supported
 * @error: on success %NULL
 *
 * List soundcard settings.
 *
 * Since: 0.4
 */
void
ags_devout_pcm_info(AgsSoundcard *soundcard,
		    char *card_id,
		    guint *channels_min, guint *channels_max,
		    guint *rate_min, guint *rate_max,
		    guint *buffer_size_min, guint *buffer_size_max,
		    GError **error)
{
  int rc;
  snd_pcm_t *handle;
  snd_pcm_hw_params_t *params;
  unsigned int val;
  int dir;
  snd_pcm_uframes_t frames;
  int err;

  /* Open PCM device for playback. */
  handle = NULL;

  rc = snd_pcm_open(&handle, card_id, SND_PCM_STREAM_PLAYBACK, 0);

  if(rc < 0) {
    g_message("unable to open pcm device: %s\n\0", snd_strerror(rc));

    g_set_error(error,
		AGS_DEVOUT_ERROR,
		AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
		"unable to open pcm device: %s\n\0",
		snd_strerror(rc));

    return;
  }

  /* Allocate a hardware parameters object. */
  snd_pcm_hw_params_alloca(&params);

  /* Fill it in with default values. */
  snd_pcm_hw_params_any(handle, params);

  /* channels */
  snd_pcm_hw_params_get_channels_min(params, &val);
  *channels_min = val;

  snd_pcm_hw_params_get_channels_max(params, &val);
  *channels_max = val;

  /* samplerate */
  dir = 0;
  snd_pcm_hw_params_get_rate_min(params, &val, &dir);
  *rate_min = val;

  dir = 0;
  snd_pcm_hw_params_get_rate_max(params, &val, &dir);
  *rate_max = val;

  /* buffer size */
  dir = 0;
  snd_pcm_hw_params_get_buffer_size_min(params, &frames);
  *buffer_size_min = frames;

  dir = 0;
  snd_pcm_hw_params_get_buffer_size_max(params, &frames);
  *buffer_size_max = frames;

  snd_pcm_close(handle);
}
コード例 #5
0
static int
palsa_set_hw_params (ddb_waveformat_t *fmt) {
    snd_pcm_hw_params_t *hw_params = NULL;
    int err = 0;

    memcpy (&plugin.fmt, fmt, sizeof (ddb_waveformat_t));
    if (!plugin.fmt.channels) {
        // generic format
        plugin.fmt.bps = 16;
        plugin.fmt.is_float = 0;
        plugin.fmt.channels = 2;
        plugin.fmt.samplerate = 44100;
        plugin.fmt.channelmask = 3;
    }

    snd_pcm_nonblock(audio, 0);
    snd_pcm_drain (audio);
    snd_pcm_nonblock(audio, 1);

    if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
        fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
                snd_strerror (err));
        goto error;
    }

    if ((err = snd_pcm_hw_params_any (audio, hw_params)) < 0) {
        fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
                snd_strerror (err));
        goto error;
    }

    if ((err = snd_pcm_hw_params_set_access (audio, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        fprintf (stderr, "cannot set access type (%s)\n",
                snd_strerror (err));
        goto error;
    }

    snd_pcm_format_t sample_fmt;
    switch (plugin.fmt.bps) {
    case 8:
        sample_fmt = SND_PCM_FORMAT_S8;
        break;
    case 16:
#if WORDS_BIGENDIAN
        sample_fmt = SND_PCM_FORMAT_S16_BE;
#else
        sample_fmt = SND_PCM_FORMAT_S16_LE;
#endif
        break;
    case 24:
#if WORDS_BIGENDIAN
        sample_fmt = SND_PCM_FORMAT_S24_3BE;
#else
        sample_fmt = SND_PCM_FORMAT_S24_3LE;
#endif
        break;
    case 32:
        if (plugin.fmt.is_float) {
#if WORDS_BIGENDIAN
            sample_fmt = SND_PCM_FORMAT_FLOAT_BE;
#else
            sample_fmt = SND_PCM_FORMAT_FLOAT_LE;
#endif
        }
        else {
#if WORDS_BIGENDIAN
            sample_fmt = SND_PCM_FORMAT_S32_BE;
#else
            sample_fmt = SND_PCM_FORMAT_S32_LE;
#endif
        }
        break;
    }

    if ((err = snd_pcm_hw_params_set_format (audio, hw_params, sample_fmt)) < 0) {
        fprintf (stderr, "cannot set sample format to %d bps (error: %s), trying all supported formats\n", plugin.fmt.bps, snd_strerror (err));

        int fmt_cnt[] = { 16, 24, 32, 32, 8 };
#if WORDS_BIGENDIAN
        int fmt[] = { SND_PCM_FORMAT_S16_BE, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_S32_BE, SND_PCM_FORMAT_FLOAT_BE, SND_PCM_FORMAT_S8, -1 };
#else
        int fmt[] = { SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_S32_LE, SND_PCM_FORMAT_FLOAT_LE, SND_PCM_FORMAT_S8, -1 };
#endif

        // 1st try formats with higher bps
        int i = 0;
        for (i = 0; fmt[i] != -1; i++) {
            if (fmt[i] != sample_fmt && fmt_cnt[i] > plugin.fmt.bps) {
                if (snd_pcm_hw_params_set_format (audio, hw_params, fmt[i]) >= 0) {
                    fprintf (stderr, "Found compatible format %d bps\n", fmt_cnt[i]);
                    sample_fmt = fmt[i];
                    break;
                }
            }
        }
        if (fmt[i] == -1) {
            // next try formats with lower bps
            i = 0;
            for (i = 0; fmt[i] != -1; i++) {
                if (fmt[i] != sample_fmt && fmt_cnt[i] < plugin.fmt.bps) {
                    if (snd_pcm_hw_params_set_format (audio, hw_params, fmt[i]) >= 0) {
                        fprintf (stderr, "Found compatible format %d bps\n", fmt_cnt[i]);
                        sample_fmt = fmt[i];
                        break;
                    }
                }
            }
        }

        if (fmt[i] == -1) {
            fprintf (stderr, "Fallback format could not be found\n");
            goto error;
        }
    }

    snd_pcm_hw_params_get_format (hw_params, &sample_fmt);
    trace ("chosen sample format: %04Xh\n", (int)sample_fmt);

    int val = plugin.fmt.samplerate;
    int ret = 0;

    if ((err = snd_pcm_hw_params_set_rate_resample (audio, hw_params, conf_alsa_resample)) < 0) {
        fprintf (stderr, "cannot setup resampling (%s)\n",
                snd_strerror (err));
        goto error;
    }

    if ((err = snd_pcm_hw_params_set_rate_near (audio, hw_params, &val, &ret)) < 0) {
        fprintf (stderr, "cannot set sample rate (%s)\n",
                snd_strerror (err));
        goto error;
    }
    plugin.fmt.samplerate = val;
    trace ("chosen samplerate: %d Hz\n", val);

    int chanmin, chanmax;
    snd_pcm_hw_params_get_channels_min (hw_params, &chanmin);
    snd_pcm_hw_params_get_channels_max (hw_params, &chanmax);

    trace ("minchan: %d, maxchan: %d\n", chanmin, chanmax);
    int nchan = plugin.fmt.channels;
    if (nchan > chanmax) {
        nchan = chanmax;
    }
    else if (nchan < chanmin) {
        nchan = chanmin;
    }
    trace ("setting chan=%d\n", nchan);
    if ((err = snd_pcm_hw_params_set_channels (audio, hw_params, nchan)) < 0) {
        fprintf (stderr, "cannot set channel count (%s)\n",
                snd_strerror (err));
    }

    snd_pcm_hw_params_get_channels (hw_params, &nchan);
    trace ("alsa channels: %d\n", nchan);

    req_buffer_size = deadbeef->conf_get_int ("alsa.buffer", DEFAULT_BUFFER_SIZE);
    req_period_size = deadbeef->conf_get_int ("alsa.period", DEFAULT_PERIOD_SIZE);
    buffer_size = req_buffer_size;
    period_size = req_period_size;
    trace ("trying buffer size: %d frames\n", (int)buffer_size);
    trace ("trying period size: %d frames\n", (int)period_size);
    snd_pcm_hw_params_set_buffer_size_near (audio, hw_params, &buffer_size);
    snd_pcm_hw_params_set_period_size_near (audio, hw_params, &period_size, NULL);
    trace ("alsa buffer size: %d frames\n", (int)buffer_size);
    trace ("alsa period size: %d frames\n", (int)period_size);

    if ((err = snd_pcm_hw_params (audio, hw_params)) < 0) {
        fprintf (stderr, "cannot set parameters (%s)\n",
                snd_strerror (err));
        goto error;
    }

    plugin.fmt.is_float = 0;
    switch (sample_fmt) {
    case SND_PCM_FORMAT_S8:
        plugin.fmt.bps = 8;
        break;
    case SND_PCM_FORMAT_S16_BE:
    case SND_PCM_FORMAT_S16_LE:
        plugin.fmt.bps = 16;
        break;
    case SND_PCM_FORMAT_S24_3BE:
    case SND_PCM_FORMAT_S24_3LE:
        plugin.fmt.bps = 24;
        break;
    case SND_PCM_FORMAT_S32_BE:
    case SND_PCM_FORMAT_S32_LE:
        plugin.fmt.bps = 32;
        break;
    case SND_PCM_FORMAT_FLOAT_LE:
    case SND_PCM_FORMAT_FLOAT_BE:
        plugin.fmt.bps = 32;
        plugin.fmt.is_float = 1;
        break;
    }

    trace ("chosen bps: %d (%s)\n", plugin.fmt.bps, plugin.fmt.is_float ? "float" : "int");

    plugin.fmt.channels = nchan;
    plugin.fmt.channelmask = 0;
    if (nchan == 1) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT;
    }
    if (nchan == 2) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT;
    }
    if (nchan == 3) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_LOW_FREQUENCY;
    }
    if (nchan == 4) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT;
    }
    if (nchan == 5) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER;
    }
    if (nchan == 6) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER | DDB_SPEAKER_LOW_FREQUENCY;
    }
    if (nchan == 7) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER | DDB_SPEAKER_SIDE_LEFT | DDB_SPEAKER_SIDE_RIGHT;
    }
    if (nchan == 8) {
        plugin.fmt.channelmask = DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT | DDB_SPEAKER_BACK_LEFT | DDB_SPEAKER_BACK_RIGHT | DDB_SPEAKER_FRONT_CENTER | DDB_SPEAKER_SIDE_LEFT | DDB_SPEAKER_SIDE_RIGHT | DDB_SPEAKER_LOW_FREQUENCY;
    }
error:
    if (err < 0) {
        memset (&plugin.fmt, 0, sizeof (ddb_waveformat_t));
    }
    if (hw_params) {
        snd_pcm_hw_params_free (hw_params);
    }
    return err;
}
コード例 #6
0
ファイル: s_audio_alsamm.c プロジェクト: porres/pure-data
/* ------- PCM INITS --------------------------------- */
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params,int *chs)
{
#ifndef ALSAAPI9
  unsigned int rrate;
  int err, dir;
  int channels_allocated = 0;

  /* choose all parameters */
  err = snd_pcm_hw_params_any(handle, params);
  if (err < 0) {
    check_error(err,"Broken configuration: no configurations available");
    return err;
  }

  /* set the nointerleaved read/write format */
  err = snd_pcm_hw_params_set_access(handle, params,
                                     SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
  if (err >= 0) {
#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("Access type %s available","SND_PCM_ACCESS_MMAP_NONINTERLEAVED");
#endif
  }
  else{
    check_error(err,"No Accesstype SND_PCM_ACCESS_MMAP_NONINTERLEAVED");
    return err;
  }

  /* set the sample format */
  err = snd_pcm_hw_params_set_format(handle, params, ALSAMM_FORMAT);
  if (err < 0) {
    check_error(err,"Sample format not available for playback");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("Setting format to %s",snd_pcm_format_name(ALSAMM_FORMAT));
#endif

  /* first check samplerate since channels numbers
     are samplerate dependent (double speed) */
  /* set the stream rate */

  rrate = alsamm_sr;

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("Samplerate request: %i Hz",rrate);
#endif

  dir=-1;
  err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, &dir);
  if (err < 0) {
    check_error(err,"Rate not available");
    return err;
  }

  if (rrate != alsamm_sr) {
    post("Warning: rate %iHz doesn't match requested %iHz", rrate,alsamm_sr);
    alsamm_sr = rrate;
  }
  else
    if(sys_verbose)
      post("Samplerate is set to %iHz",alsamm_sr);

  /* Info on channels */
  {
    int maxchs,minchs,channels = *chs;

    if((err = snd_pcm_hw_params_get_channels_max(params,
        (unsigned int *)&maxchs)) < 0){
      check_error(err,"Getting channels_max not available");
      return err;
    }
    if((err = snd_pcm_hw_params_get_channels_min(params,
        (unsigned int *)&minchs)) < 0){
      check_error(err,"Getting channels_min not available");
      return err;
    }

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("Getting channels:min=%d, max= %d for request=%d",minchs,maxchs,channels);
#endif
    if(channels < 0)channels=maxchs;
    if(channels > maxchs)channels = maxchs;
    if(channels < minchs)channels = minchs;

    if(channels != *chs)
      post("requested channels=%d but used=%d",*chs,channels);

    *chs = channels;
#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("trying to use channels: %d",channels);
#endif
  }

  /* set the count of channels */
  err = snd_pcm_hw_params_set_channels(handle, params, *chs);
  if (err < 0) {
    check_error(err,"Channels count not available");
    return err;
  }

  /* testing for channels */
  if((err = snd_pcm_hw_params_get_channels(params,(unsigned int *)chs)) < 0)
    check_error(err,"Get channels not available");
#ifdef ALSAMM_DEBUG
  else
    if(sys_verbose)
      post("When setting channels count and got %d",*chs);
#endif

  /* if buffersize is set use this instead buffertime */
  if(alsamm_buffersize > 0){

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("hw_params: ask for max buffersize of %d samples",
           (unsigned int) alsamm_buffersize );
#endif

    alsamm_buffer_size = alsamm_buffersize;

    err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
        (unsigned long *)&alsamm_buffer_size);
    if (err < 0) {
      check_error(err,"Unable to set max buffer size");
      return err;
    }

  }
  else{
    if(alsamm_buffertime <= 0) /* should never happen, but use 20ms */
      alsamm_buffertime = 20000;

#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("hw_params: ask for max buffertime of %d ms",
           (unsigned int) (alsamm_buffertime*0.001) );
#endif

    err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
        &alsamm_buffertime, &dir);
    if (err < 0) {
      check_error(err,"Unable to set max buffer time");
      return err;
    }
  }

  err = snd_pcm_hw_params_get_buffer_time(params,
    (unsigned int *)&alsamm_buffertime, &dir);
  if (err < 0) {
    check_error(err,"Unable to get buffer time");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("hw_params: got buffertime to %f ms",
         (float) (alsamm_buffertime*0.001));
#endif

  err = snd_pcm_hw_params_get_buffer_size(params,
    (unsigned long *)&alsamm_buffer_size);
  if (err < 0) {
    check_error(err,"Unable to get buffer size");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("hw_params: got  buffersize to %d samples",(int) alsamm_buffer_size);
#endif

  err = snd_pcm_hw_params_get_period_size(params,
    (unsigned long *)&alsamm_period_size, &dir);
  if (err > 0) {
    check_error(err,"Unable to get period size");
    return err;
  }

#ifdef ALSAMM_DEBUG
  if(sys_verbose)
    post("Got period size of %d", (int) alsamm_period_size);
#endif
  {
    unsigned int pmin,pmax;

    err = snd_pcm_hw_params_get_periods_min(params, &pmin, &dir);
    if (err > 0) {
      check_error(err,"Unable to get period size");
      return err;
    }
    err = snd_pcm_hw_params_get_periods_min(params, &pmax, &dir);
    if (err > 0) {
      check_error(err,"Unable to get period size");
      return err;
    }

    /* use maximum of periods */
    if( alsamm_periods <= 0)
      alsamm_periods = pmax;
    alsamm_periods = (alsamm_periods > pmax)?pmax:alsamm_periods;
    alsamm_periods = (alsamm_periods < pmin)?pmin:alsamm_periods;

    err = snd_pcm_hw_params_set_periods(handle, params, alsamm_periods, dir);
    if (err > 0) {
      check_error(err,"Unable to set periods");
      return err;
    }


    err = snd_pcm_hw_params_get_periods(params, &pmin, &dir);
    if (err > 0) {
      check_error(err,"Unable to get periods");
      return err;
    }
#ifdef ALSAMM_DEBUG
    if(sys_verbose)
      post("Got periods of %d, where periodsmin=%d, periodsmax=%d",
           alsamm_periods,pmin,pmax);
#endif
  }

  /* write the parameters to device */
  err = snd_pcm_hw_params(handle, params);
  if (err < 0) {
    check_error(err,"Unable to set hw params");
    return err;
  }
#endif /* ALSAAPI9 */
  return 0;
}
コード例 #7
0
ファイル: alsa.c プロジェクト: ecthiender/mocp-git
/* Fill caps with the device capabilities. Return 0 on error. */
static int fill_capabilities (struct output_driver_caps *caps)
{
	snd_pcm_hw_params_t *hw_params;
	snd_pcm_format_mask_t *format_mask;
	int err;
	unsigned val;

	if ((err = snd_pcm_open(&handle, options_get_str("AlsaDevice"),
					SND_PCM_STREAM_PLAYBACK,
					SND_PCM_NONBLOCK)) < 0) {
		error ("Can't open audio: %s", snd_strerror(err));
		return 0;
	}

	if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
		error ("Can't allocate alsa hardware parameters structure: %s",
				snd_strerror(err));
		snd_pcm_close (handle);
		return 0;
	}

	if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
		error ("Can't initialize hardware parameters structure: %s",
				snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}

	if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &val)) < 0) {
		error ("Can't get the minimum number of channels: %s",
				snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}
	caps->min_channels = val;
	
	if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &val)) < 0) {
		error ("Can't get the maximum number of channels: %s",
				snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}
	caps->max_channels = val;

	if ((err = snd_pcm_format_mask_malloc(&format_mask)) < 0) {
		error ("Can't allocate format mask: %s", snd_strerror(err));
		snd_pcm_hw_params_free (hw_params);
		snd_pcm_close (handle);
		return 0;
	}
	snd_pcm_hw_params_get_format_mask (hw_params, format_mask);

	caps->formats = SFMT_NE;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S8))
		caps->formats |= SFMT_S8;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U8))
		caps->formats |= SFMT_U8;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S16))
		caps->formats |= SFMT_S16;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U16))
		caps->formats |= SFMT_U16;
#if 0
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S24))
		caps->formats |= SFMT_S32; /* conversion needed */
#endif
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_S32))
		caps->formats |= SFMT_S32;
	if (snd_pcm_format_mask_test(format_mask, SND_PCM_FORMAT_U32))
		caps->formats |= SFMT_U32;

	snd_pcm_format_mask_free (format_mask);
	snd_pcm_hw_params_free (hw_params);
	snd_pcm_close (handle);
	handle = NULL;

	return 1;
}
コード例 #8
0
static void
device_test (GtkWidget *w, alsa_driver *d)
{
    guint chmin, chmax, i;
    gint err;
    gchar *new_device;

    d->can8 = FALSE;
    d->can16 = FALSE;
    d->canmono = FALSE;
    d->canstereo = FALSE;
    d->signedness8 = FALSE;
    d->signedness16 = FALSE;

    new_device = gtk_combo_box_get_active_text(GTK_COMBO_BOX(d->alsa_device));
    if(g_ascii_strcasecmp(d->device, new_device)) {
	g_free(d->device);
	d->device = g_strdup(new_device);
	gui_hlp_combo_box_prepend_text_or_set_active(GTK_COMBO_BOX(d->alsa_device), d->device, FALSE);
    }

    for(i = 0; i < NUM_FORMATS; i++){
	d->devcap[i].minfreq = 8000;
	d->devcap[i].maxfreq = 44100;
	d->devcap[i].minbufsize = 256;
    }
    d->devcap[MONO8].maxbufsize = 65536;
    d->devcap[STEREO8].maxbufsize = 32768;
    d->devcap[MONO16].maxbufsize = 32768;
    d->devcap[STEREO16].maxbufsize = 16384;

    if(pcm_open_and_load_hwparams(d) < 0)
	return;

    if(!snd_pcm_hw_params_test_format(d->soundfd, d->hwparams, SND_PCM_FORMAT_U8)) {
	d->can8 = TRUE;
    }
    if(!snd_pcm_hw_params_test_format(d->soundfd, d->hwparams, SND_PCM_FORMAT_S8)) {
	d->can8 = TRUE;
	d->signedness8 = TRUE;
    }
    if(!snd_pcm_hw_params_test_format(d->soundfd, d->hwparams, SND_PCM_FORMAT_U16)) {
	d->can16 = TRUE;
    }
    if(!snd_pcm_hw_params_test_format(d->soundfd, d->hwparams, SND_PCM_FORMAT_S16)) {
	d->can16 = TRUE;
	d->signedness16 = TRUE;
    }

    if((err = snd_pcm_hw_params_get_channels_min(d->hwparams, &chmin)) < 0) {
	alsa_error(N_("Unable to get minimal channels number"), err);
	snd_pcm_close(d->soundfd);
	return;
    }
    if((err = snd_pcm_hw_params_get_channels_max(d->hwparams, &chmax)) < 0) {
	alsa_error(N_("Unable to get maximal channels number"), err);
	snd_pcm_close(d->soundfd);
	return;
    }
    if(chmin > 2) {
	error_error("Both mono and stereo are not supported by ALSA device!!!");
	snd_pcm_close(d->soundfd);
	return;
    }
    if(chmin == 1)
	d->canmono = TRUE;
    if(chmax >= 2)
	d->canstereo = TRUE;

    if(d->can8) {
	if((err = snd_pcm_hw_params_set_format(d->soundfd, d->hwparams,
					d->signedness8 ? SND_PCM_FORMAT_S8 : SND_PCM_FORMAT_U8)) < 0) {
	    alsa_error(N_("Unable to set audio format"), err);
	    snd_pcm_close(d->soundfd);
	    return;
	}
	if(d->canmono) {
	    if(set_rates(d, 1, MONO8) < 0) {
		snd_pcm_close(d->soundfd);
		return;
	    }
	}

	if(d->canstereo) {
	    snd_pcm_close(d->soundfd);
	    if(pcm_open_and_load_hwparams(d) < 0)
		return;
	    if(set_rates(d, 2, STEREO8) < 0) {
		snd_pcm_close(d->soundfd);
		return;
	    }
	}
    }

    if(d->can16) {
	snd_pcm_close(d->soundfd);
	if(pcm_open_and_load_hwparams(d) < 0)
	    return;
	if((err = snd_pcm_hw_params_set_format(d->soundfd, d->hwparams,
					d->signedness16 ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U16)) < 0) {
	    alsa_error(N_("Unable to set audio format"), err);
	    snd_pcm_close(d->soundfd);
	    return;
	}
	if(d->canmono) {
	    if(set_rates(d, 1, MONO16) < 0) {
		snd_pcm_close(d->soundfd);
		return;
	    }
	}
	if(d->canstereo) {
	    snd_pcm_close(d->soundfd);
	    if(pcm_open_and_load_hwparams(d) < 0)
		return;
	    if(set_rates(d, 2, STEREO16) < 0) {
		snd_pcm_close(d->soundfd);
		return;
	    }
	}
    }

    snd_pcm_close(d->soundfd);
    update_controls(d);
}
コード例 #9
0
ファイル: AlsaRenderer.cpp プロジェクト: ClarkWang12/mous
bool AlsaRenderer::SetupHwParams()
{
    snd_pcm_hw_params_t* params;

    /* allocate a hardware parameters object */
    snd_pcm_hw_params_malloc(&params);

    /* choose all parameters */
    snd_pcm_hw_params_any(m_PcmHandle, params);

    /* enable hardware resampling */
    snd_pcm_hw_params_set_rate_resample(m_PcmHandle, params, m_Resample);

    /* set the interleaved read/write format */
    snd_pcm_hw_params_set_access(m_PcmHandle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

    /* signed 16-bit little-endian format */
    snd_pcm_hw_params_set_format(m_PcmHandle, params, SND_PCM_FORMAT_S16_LE);

    /* set the count of channels */
    snd_pcm_hw_params_get_channels_max(params, &m_Channels.max);
    snd_pcm_hw_params_get_channels_min(params, &m_Channels.min);
    if (m_Channels.val < m_Channels.min || m_Channels.val > m_Channels.max) 
        m_Channels.val = m_Channels.min;
    snd_pcm_hw_params_set_channels(m_PcmHandle, params, m_Channels.val);

    /* set the stream rate */
    snd_pcm_hw_params_get_rate_max(params, &m_SampleRate.max, &m_Dir);
    snd_pcm_hw_params_get_rate_min(params, &m_SampleRate.min, &m_Dir);
    if (m_SampleRate.val < m_SampleRate.min || m_SampleRate.val > m_SampleRate.max)
        m_SampleRate.val = m_SampleRate.min;
    printf("sample rate max:%d, min:%d, val:%d\n", 
            m_SampleRate.max, m_SampleRate.min, m_SampleRate.val);
    snd_pcm_hw_params_set_rate(m_PcmHandle, params, m_SampleRate.val, m_Dir);

    /* we can set period and buffer by size or time */
    /* by default we use "size" (count of frames)   */

    /* set how many frames in a buffer (a buffer cantains several periods) */
    snd_pcm_hw_params_get_buffer_size_max(params, &m_BufferSize.max);
    snd_pcm_hw_params_get_buffer_size_min(params, &m_BufferSize.min);

    /* detect period time and buffer time range  */
    snd_pcm_hw_params_get_buffer_time_max(params, &m_BufferTime.max, &m_Dir);
    snd_pcm_hw_params_get_buffer_time_min(params, &m_BufferTime.min, &m_Dir);
    m_BufferTime.val = std::max(m_BufferTime.max / 2, m_BufferTime.min); 
    //m_BufferTime.val = m_BufferTime.min + (m_BufferTime.max - m_BufferTime.min) /2; 
    printf("buffer time max:%d, min:%d, val:%d\n", 
            m_BufferTime.max, m_BufferTime.min, m_BufferTime.val);
    //(m_BufferTime.max > 120000) ? 120000 : m_BufferTime.max;//120000
    snd_pcm_hw_params_set_buffer_time_near(m_PcmHandle, params, &m_BufferTime.val, &m_Dir);

    snd_pcm_hw_params_get_period_time_max(params, &m_PeriodTime.max, &m_Dir);
    snd_pcm_hw_params_get_period_time_min(params, &m_PeriodTime.min, &m_Dir);
    m_PeriodTime.val = m_BufferTime.val / 4;
    //m_PeriodTime.val = m_PeriodTime.min + (m_PeriodTime.max - m_PeriodTime.min) / 2;
    printf("period time max:%d, min:%d, val:%d\n", 
            m_PeriodTime.max, m_PeriodTime.min, m_PeriodTime.val);
    snd_pcm_hw_params_set_period_time_near(m_PcmHandle, params, &m_PeriodTime.val, &m_Dir);

    int ret = snd_pcm_hw_params(m_PcmHandle, params);

    if (ret != 0) {
        snd_pcm_hw_params_free(params);
        return false;
    }

    // get period size again
    snd_pcm_hw_params_get_period_size(params, &m_PeriodSize.val, &m_Dir);
    snd_pcm_hw_params_get_buffer_size(params, &m_BufferSize.val);

    m_BitsPerSample = snd_pcm_format_physical_width(SND_PCM_FORMAT_S16_LE);
    m_FrameLength = (m_BitsPerSample/8 * m_Channels.val);
    //mPeriodBufferLength = m_PeriodSize.val * m_FrameLength ;

    snd_pcm_hw_params_free(params);

    return true;
}
コード例 #10
0
ファイル: AudioTest.c プロジェクト: tician/nan-darwin-op
int main(int argc, char *argv[])
{
  const char *device_name = "hw";
  snd_pcm_t *pcm;
  snd_pcm_hw_params_t *hw_params;
  unsigned int i;
  unsigned int min, max;
  int any_rate;
  int err;

  if (argc > 1)
    device_name = argv[1];

  err = snd_pcm_open(&pcm, device_name, SND_PCM_STREAM_CAPTURE, 
		     SND_PCM_NONBLOCK);
  if (err < 0) {
    fprintf(stderr, "cannot open device '%s': %s\n", device_name, 
	    snd_strerror(err));
    return 1;
  }

  snd_pcm_hw_params_alloca(&hw_params);
  err = snd_pcm_hw_params_any(pcm, hw_params);
  if (err < 0) {
    fprintf(stderr, "cannot get hardware parameters: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }

  printf("Device: %s (type: %s)\n", device_name, 
	 snd_pcm_type_name(snd_pcm_type(pcm)));

  printf("Access types:");
  for (i = 0; i < ARRAY_SIZE(accesses); ++i) {
    if (!snd_pcm_hw_params_test_access(pcm, hw_params, accesses[i]))
      printf(" %s", snd_pcm_access_name(accesses[i]));
  }
  putchar('\n');

  printf("Formats:");
  for (i = 0; i < ARRAY_SIZE(formats); ++i) {
    if (!snd_pcm_hw_params_test_format(pcm, hw_params, formats[i]))
      printf(" %s", snd_pcm_format_name(formats[i]));
  }
  putchar('\n');

  err = snd_pcm_hw_params_get_channels_min(hw_params, &min);
  if (err < 0) {
    fprintf(stderr, "cannot get minimum channels count: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  err = snd_pcm_hw_params_get_channels_max(hw_params, &max);
  if (err < 0) {
    fprintf(stderr, "cannot get maximum channels count: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  printf("Channels:");
  for (i = min; i <= max; ++i) {
    if (!snd_pcm_hw_params_test_channels(pcm, hw_params, i))
      printf(" %u", i);
  }
  putchar('\n');

  err = snd_pcm_hw_params_get_rate_min(hw_params, &min, NULL);
  if (err < 0) {
    fprintf(stderr, "cannot get minimum rate: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  err = snd_pcm_hw_params_get_rate_max(hw_params, &max, NULL);
  if (err < 0) {
    fprintf(stderr, "cannot get maximum rate: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  printf("Sample rates:");
  if (min == max)
    printf(" %u", min);
  else if (!snd_pcm_hw_params_test_rate(pcm, hw_params, min + 1, 0))
    printf(" %u-%u", min, max);
  else {
    any_rate = 0;
    for (i = 0; i < ARRAY_SIZE(rates); ++i) {
      if (!snd_pcm_hw_params_test_rate(pcm, hw_params, 
				       rates[i], 0)) {
	any_rate = 1;
	printf(" %u", rates[i]);
      }
    }
    if (!any_rate)
      printf(" %u-%u", min, max);
  }
  putchar('\n');

  err = snd_pcm_hw_params_get_period_time_min(hw_params, &min, NULL);
  if (err < 0) {
    fprintf(stderr, "cannot get minimum period time: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  err = snd_pcm_hw_params_get_period_time_max(hw_params, &max, NULL);
  if (err < 0) {
    fprintf(stderr, "cannot get maximum period time: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  printf("Interrupt interval: %u-%u us\n", min, max);

  err = snd_pcm_hw_params_get_buffer_time_min(hw_params, &min, NULL);
  if (err < 0) {
    fprintf(stderr, "cannot get minimum buffer time: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &max, NULL);
  if (err < 0) {
    fprintf(stderr, "cannot get maximum buffer time: %s\n", 
	    snd_strerror(err));
    snd_pcm_close(pcm);
    return 1;
  }
  printf("Buffer size: %u-%u us\n", min, max);

  snd_pcm_close(pcm);
  return 0;
}
コード例 #11
0
void info(char *dev_name, snd_pcm_stream_t stream) {
  snd_pcm_hw_params_t *hw_params;
  int err;
  snd_pcm_t *handle;
  unsigned int max;
  unsigned int min;
  unsigned int val;
  unsigned  int dir;
  snd_pcm_uframes_t frames;

  if ((err = snd_pcm_open (&handle, dev_name, stream, 0)) < 0) {
    fprintf (stderr, "cannot open audio device %s (%s)\n", 
	     dev_name,
	     snd_strerror (err));
    return;
  }
		   
  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 (handle, hw_params)) < 0) {
    fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  
  if ((err = snd_pcm_hw_params_get_channels_max(hw_params, &max)) < 0) {
    fprintf (stderr, "cannot  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("max channels %d\n", max);

  if ((err = snd_pcm_hw_params_get_channels_min(hw_params, &min)) < 0) {
    fprintf (stderr, "cannot get channel info  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("min channels %d\n", min);

  /*
  if ((err = snd_pcm_hw_params_get_sbits(hw_params)) < 0) {
      fprintf (stderr, "cannot get bits info  (%s)\n",
	       snd_strerror (err));
      exit (1);
  }
  printf("bits %d\n", err);
  */

  if ((err = snd_pcm_hw_params_get_rate_min(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot get min rate (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("min rate %d hz\n", val);

  if ((err = snd_pcm_hw_params_get_rate_max(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot get max rate (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("max rate %d hz\n", val);

  
  if ((err = snd_pcm_hw_params_get_period_time_min(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot get min period time  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("min period time %d usecs\n", val);

  if ((err = snd_pcm_hw_params_get_period_time_max(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot  get max period time  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("max period time %d usecs\n", val);

  if ((err = snd_pcm_hw_params_get_period_size_min(hw_params, &frames, &dir)) < 0) {
    fprintf (stderr, "cannot  get min period size  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("min period size in frames %d\n", frames);

  if ((err = snd_pcm_hw_params_get_period_size_max(hw_params, &frames, &dir)) < 0) {
    fprintf (stderr, "cannot  get max period size (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("max period size in frames %d\n", frames);

  if ((err = snd_pcm_hw_params_get_periods_min(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot  get min periods  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("min periods per buffer %d\n", val);

  if ((err = snd_pcm_hw_params_get_periods_max(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot  get min periods (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("max periods per buffer %d\n", val);

  if ((err = snd_pcm_hw_params_get_buffer_time_min(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot get min buffer time (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("min buffer time %d usecs\n", val);

  if ((err = snd_pcm_hw_params_get_buffer_time_max(hw_params, &val, &dir)) < 0) {
    fprintf (stderr, "cannot get max buffer time  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("max buffer time %d usecs\n", val);

  if ((err = snd_pcm_hw_params_get_buffer_size_min(hw_params, &frames)) < 0) {
    fprintf (stderr, "cannot get min buffer size (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("min buffer size in frames %d\n", frames);

  if ((err = snd_pcm_hw_params_get_buffer_size_max(hw_params, &frames)) < 0) {
    fprintf (stderr, "cannot get max buffer size  (%s)\n",
	     snd_strerror (err));
    exit (1);
  }
  printf("max buffer size in frames %d\n", frames);
}
コード例 #12
0
ファイル: alsa.c プロジェクト: MichaelMcDonnell/wine
/**************************************************************************
 * 			ALSA_TraceParameters		[internal]
 *
 * used to trace format changes, hw and sw parameters
 */
void ALSA_TraceParameters(snd_pcm_hw_params_t * hw_params, snd_pcm_sw_params_t * sw, int full)
{
    int err;
    snd_pcm_format_t   format;
    snd_pcm_access_t   access;

#define X(x) ((x)? "true" : "false")
    if (full)
	TRACE("FLAGS: sampleres=%s overrng=%s pause=%s resume=%s syncstart=%s batch=%s block=%s double=%s "
	      "halfd=%s joint=%s\n",
	      X(snd_pcm_hw_params_can_mmap_sample_resolution(hw_params)),
	      X(snd_pcm_hw_params_can_overrange(hw_params)),
	      X(snd_pcm_hw_params_can_pause(hw_params)),
	      X(snd_pcm_hw_params_can_resume(hw_params)),
	      X(snd_pcm_hw_params_can_sync_start(hw_params)),
	      X(snd_pcm_hw_params_is_batch(hw_params)),
	      X(snd_pcm_hw_params_is_block_transfer(hw_params)),
	      X(snd_pcm_hw_params_is_double(hw_params)),
	      X(snd_pcm_hw_params_is_half_duplex(hw_params)),
	      X(snd_pcm_hw_params_is_joint_duplex(hw_params)));
#undef X

    err = snd_pcm_hw_params_get_access(hw_params, &access);
    if (err >= 0)
    {
	TRACE("access=%s\n", snd_pcm_access_name(access));
    }
    else
    {
	snd_pcm_access_mask_t * acmask;

        acmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_access_mask_sizeof());
	snd_pcm_hw_params_get_access_mask(hw_params, acmask);
	for ( access = SND_PCM_ACCESS_MMAP_INTERLEAVED; access <= SND_PCM_ACCESS_LAST; access++)
	    if (snd_pcm_access_mask_test(acmask, access))
		TRACE("access=%s\n", snd_pcm_access_name(access));
        HeapFree( GetProcessHeap(), 0, acmask );
    }

    err = snd_pcm_hw_params_get_format(hw_params, &format);
    if (err >= 0)
    {
	TRACE("format=%s\n", snd_pcm_format_name(format));

    }
    else
    {
	snd_pcm_format_mask_t *     fmask;

        fmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_format_mask_sizeof());
	snd_pcm_hw_params_get_format_mask(hw_params, fmask);
	for ( format = SND_PCM_FORMAT_S8; format <= SND_PCM_FORMAT_LAST ; format++)
	    if ( snd_pcm_format_mask_test(fmask, format) )
		TRACE("format=%s\n", snd_pcm_format_name(format));
        HeapFree( GetProcessHeap(), 0, fmask );
    }

    do {
      int err=0;
      unsigned int val=0;
      err = snd_pcm_hw_params_get_channels(hw_params, &val);
      if (err<0) {
        unsigned int min = 0;
        unsigned int max = 0;
        err = snd_pcm_hw_params_get_channels_min(hw_params, &min),
	err = snd_pcm_hw_params_get_channels_max(hw_params, &max);
        TRACE("channels_min=%u, channels_min_max=%u\n", min, max);
      } else {
        TRACE("channels=%d\n", val);
      }
    } while(0);
    do {
      int err=0;
      snd_pcm_uframes_t val=0;
      err = snd_pcm_hw_params_get_buffer_size(hw_params, &val);
      if (err<0) {
        snd_pcm_uframes_t min = 0;
        snd_pcm_uframes_t max = 0;
        err = snd_pcm_hw_params_get_buffer_size_min(hw_params, &min),
	err = snd_pcm_hw_params_get_buffer_size_max(hw_params, &max);
        TRACE("buffer_size_min=%lu, buffer_size_min_max=%lu\n", min, max);
      } else {
        TRACE("buffer_size=%lu\n", val);
      }
    } while(0);

#define X(x) do { \
int err=0; \
int dir=0; \
unsigned int val=0; \
err = snd_pcm_hw_params_get_##x(hw_params,&val, &dir); \
if (err<0) { \
  unsigned int min = 0; \
  unsigned int max = 0; \
  err = snd_pcm_hw_params_get_##x##_min(hw_params, &min, &dir); \
  err = snd_pcm_hw_params_get_##x##_max(hw_params, &max, &dir); \
  TRACE(#x "_min=%u " #x "_max=%u\n", min, max); \
} else \
    TRACE(#x "=%d\n", val); \
} while(0)

    X(rate);
    X(buffer_time);
    X(periods);
    do {
      int err=0;
      int dir=0;
      snd_pcm_uframes_t val=0;
      err = snd_pcm_hw_params_get_period_size(hw_params, &val, &dir);
      if (err<0) {
        snd_pcm_uframes_t min = 0;
        snd_pcm_uframes_t max = 0;
        err = snd_pcm_hw_params_get_period_size_min(hw_params, &min, &dir),
	err = snd_pcm_hw_params_get_period_size_max(hw_params, &max, &dir);
        TRACE("period_size_min=%lu, period_size_min_max=%lu\n", min, max);
      } else {
        TRACE("period_size=%lu\n", val);
      }
    } while(0);

    X(period_time);
#undef X

    if (!sw)
	return;
}
コード例 #13
0
ファイル: gstalsa.c プロジェクト: pli3/gst-plugins-base
static GstCaps *
gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
    GstCaps * in_caps)
{
  GstCaps *caps;
  guint min, max;
  gint min_chans, max_chans;
  gint err, i;

  GST_LOG_OBJECT (obj, "probing channels ...");

  if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0)
    goto min_chan_error;

  if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0)
    goto max_chan_error;

  /* note: the above functions may return (guint) -1 */
  min_chans = min;
  max_chans = max;

  if (min_chans < 0) {
    min_chans = 1;
    max_chans = GST_ALSA_MAX_CHANNELS;
  } else if (max_chans < 0) {
    max_chans = GST_ALSA_MAX_CHANNELS;
  }

  if (min_chans > max_chans) {
    gint temp;

    GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), "
        "please fix your soundcard drivers", min, max);
    temp = min_chans;
    min_chans = max_chans;
    max_chans = temp;
  }

  /* pro cards seem to return large numbers for min_channels */
  if (min_chans > GST_ALSA_MAX_CHANNELS) {
    GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
    if (max_chans < min_chans) {
      max_chans = min_chans;
    } else {
      /* only support [max_chans; max_chans] for these cards for now
       * to avoid inflating the source caps with loads of structures ... */
      min_chans = max_chans;
    }
  } else {
    min_chans = MAX (min_chans, 1);
    max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
  }

  GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
  GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);

  caps = gst_caps_new_empty ();

  for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
    GstStructure *s;
    GType field_type;
    gint c_min = min_chans;
    gint c_max = max_chans;

    s = gst_caps_get_structure (in_caps, i);
    /* the template caps might limit the number of channels (like alsasrc),
     * in which case we don't want to return a superset, so hack around this
     * for the two common cases where the channels are either a fixed number
     * or a min/max range). Example: alsasrc template has channels = [1,2] and 
     * the detection will claim to support 8 channels for device 'plughw:0' */
    field_type = gst_structure_get_field_type (s, "channels");
    if (field_type == G_TYPE_INT) {
      gst_structure_get_int (s, "channels", &c_min);
      gst_structure_get_int (s, "channels", &c_max);
    } else if (field_type == GST_TYPE_INT_RANGE) {
      const GValue *val;

      val = gst_structure_get_value (s, "channels");
      c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans);
      c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans);
    } else {
      c_min = min_chans;
      c_max = max_chans;
    }

    caps_add_channel_configuration (caps, s, c_min, c_max);
  }

  gst_caps_unref (in_caps);

  return caps;

  /* ERRORS */
min_chan_error:
  {
    GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s",
        snd_strerror (err));
    return NULL;
  }
max_chan_error:
  {
    GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s",
        snd_strerror (err));
    return NULL;
  }
}
コード例 #14
0
ファイル: waveinit.c プロジェクト: mikekap/wine
/*----------------------------------------------------------------------------
**  ALSA_ComputeCaps
**
**      Given an ALSA PCM, figure out our HW CAPS structure info.
**  ctl can be null, pcm is required, as is all output parms.
**
*/
static int ALSA_ComputeCaps(snd_ctl_t *ctl, snd_pcm_t *pcm,
        WORD *channels, DWORD *flags, DWORD *formats, DWORD *supports)
{
    snd_pcm_hw_params_t *hw_params;
    snd_pcm_format_mask_t *fmask;
    snd_pcm_access_mask_t *acmask;
    unsigned int ratemin = 0;
    unsigned int ratemax = 0;
    unsigned int chmin = 0;
    unsigned int chmax = 0;
    int rc, dir = 0;

    hw_params = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_hw_params_sizeof() );
    fmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_format_mask_sizeof() );
    acmask = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_access_mask_sizeof() );

    if ((rc = snd_pcm_hw_params_any(pcm, hw_params)) < 0) goto done;

    snd_pcm_hw_params_get_format_mask(hw_params, fmask);

    if ((rc = snd_pcm_hw_params_get_access_mask(hw_params, acmask)) < 0) goto done;

    if ((rc = snd_pcm_hw_params_get_rate_min(hw_params, &ratemin, &dir)) < 0) goto done;
    if ((rc = snd_pcm_hw_params_get_rate_max(hw_params, &ratemax, &dir)) < 0) goto done;
    if ((rc = snd_pcm_hw_params_get_channels_min(hw_params, &chmin)) < 0) goto done;
    if ((rc = snd_pcm_hw_params_get_channels_max(hw_params, &chmax)) < 0) goto done;

#define X(r,v) \
    if ( (r) >= ratemin && ( (r) <= ratemax || ratemax == -1) ) \
    { \
       if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_U8)) \
       { \
          if (chmin <= 1 && 1 <= chmax) \
              *formats |= WAVE_FORMAT_##v##M08; \
          if (chmin <= 2 && 2 <= chmax) \
              *formats |= WAVE_FORMAT_##v##S08; \
       } \
       if (snd_pcm_format_mask_test( fmask, SND_PCM_FORMAT_S16_LE)) \
       { \
          if (chmin <= 1 && 1 <= chmax) \
              *formats |= WAVE_FORMAT_##v##M16; \
          if (chmin <= 2 && 2 <= chmax) \
              *formats |= WAVE_FORMAT_##v##S16; \
       } \
    }
    X(11025,1);
    X(22050,2);
    X(44100,4);
    X(48000,48);
    X(96000,96);
#undef X

    if (chmin > 1)
        FIXME("Device has a minimum of %d channels\n", chmin);
    *channels = chmax;

    /* FIXME: is sample accurate always true ?
    ** Can we do WAVECAPS_PITCH, WAVECAPS_SYNC, or WAVECAPS_PLAYBACKRATE? */
    *supports |= WAVECAPS_SAMPLEACCURATE;

    *supports |= WAVECAPS_DIRECTSOUND;

    /* check for volume control support */
    if (ctl) {
        if (snd_ctl_name(ctl))
        {
            snd_hctl_t *hctl;
            if (snd_hctl_open(&hctl, snd_ctl_name(ctl), 0) >= 0)
            {
                snd_hctl_load(hctl);
                if (!ALSA_CheckSetVolume( hctl, NULL, NULL, NULL, NULL, NULL, NULL, NULL ))
                {
                    *supports |= WAVECAPS_VOLUME;
                    if (chmin <= 2 && 2 <= chmax)
                        *supports |= WAVECAPS_LRVOLUME;
                }
                snd_hctl_free(hctl);
                snd_hctl_close(hctl);
            }
        }
    }

    *flags = DSCAPS_CERTIFIED | DSCAPS_CONTINUOUSRATE;
    *flags |= DSCAPS_SECONDARYMONO | DSCAPS_SECONDARYSTEREO;
    *flags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT;

    if (*formats & (WAVE_FORMAT_1M08  | WAVE_FORMAT_2M08  |
                               WAVE_FORMAT_4M08  | WAVE_FORMAT_48M08 |
                               WAVE_FORMAT_96M08 | WAVE_FORMAT_1M16  |
                               WAVE_FORMAT_2M16  | WAVE_FORMAT_4M16  |
                               WAVE_FORMAT_48M16 | WAVE_FORMAT_96M16) )
        *flags |= DSCAPS_PRIMARYMONO;

    if (*formats & (WAVE_FORMAT_1S08  | WAVE_FORMAT_2S08  |
                               WAVE_FORMAT_4S08  | WAVE_FORMAT_48S08 |
                               WAVE_FORMAT_96S08 | WAVE_FORMAT_1S16  |
                               WAVE_FORMAT_2S16  | WAVE_FORMAT_4S16  |
                               WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
        *flags |= DSCAPS_PRIMARYSTEREO;

    if (*formats & (WAVE_FORMAT_1M08  | WAVE_FORMAT_2M08  |
                               WAVE_FORMAT_4M08  | WAVE_FORMAT_48M08 |
                               WAVE_FORMAT_96M08 | WAVE_FORMAT_1S08  |
                               WAVE_FORMAT_2S08  | WAVE_FORMAT_4S08  |
                               WAVE_FORMAT_48S08 | WAVE_FORMAT_96S08) )
        *flags |= DSCAPS_PRIMARY8BIT;

    if (*formats & (WAVE_FORMAT_1M16  | WAVE_FORMAT_2M16  |
                               WAVE_FORMAT_4M16  | WAVE_FORMAT_48M16 |
                               WAVE_FORMAT_96M16 | WAVE_FORMAT_1S16  |
                               WAVE_FORMAT_2S16  | WAVE_FORMAT_4S16  |
                               WAVE_FORMAT_48S16 | WAVE_FORMAT_96S16) )
        *flags |= DSCAPS_PRIMARY16BIT;

    rc = 0;

done:
    if (rc < 0) ERR("failed: %s(%d)\n", snd_strerror(rc), rc);
    HeapFree( GetProcessHeap(), 0, hw_params );
    HeapFree( GetProcessHeap(), 0, fmask );
    HeapFree( GetProcessHeap(), 0, acmask );
    return rc;
}
コード例 #15
0
ファイル: audioinputalsa.cpp プロジェクト: kzmi/mythtv_isdb
bool AudioInputALSA::PrepHwParams(void)
{
    snd_pcm_hw_params_t* hwparams;
    snd_pcm_hw_params_alloca(&hwparams);
    if (AlsaBad(snd_pcm_hw_params_any(pcm_handle, hwparams),
                "failed to init hw params"))
        return false;
    snd_pcm_access_t axs = SND_PCM_ACCESS_RW_INTERLEAVED; //always?
    if (AlsaBad(snd_pcm_hw_params_set_access(pcm_handle, hwparams, axs),
                "failed to set interleaved rw io"))
        return false;
    snd_pcm_format_t format =
        (m_audio_sample_bits > 8) ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U8;
    if (AlsaBad(snd_pcm_hw_params_set_format(pcm_handle, hwparams, format),
                QString("failed to set sample format %1")
                .arg(snd_pcm_format_description(format))))
        return false;
    if (VERBOSE_LEVEL_CHECK(VB_AUDIO, LOG_DEBUG))
    {
        uint min_chans, max_chans;
        if(AlsaBad(snd_pcm_hw_params_get_channels_min(hwparams, &min_chans),
                   QString("unable to get min channel count")))
            min_chans = 0;
        if(AlsaBad(snd_pcm_hw_params_get_channels_max(hwparams, &max_chans),
                   QString("unable to get max channel count")))
            max_chans = 0;
        LOG(VB_AUDIO, LOG_DEBUG, LOC_DEV +
            QString("min channels %1, max channels %2, myth requests %3")
            .arg(min_chans).arg(max_chans).arg(m_audio_channels));
    }
    if (AlsaBad(snd_pcm_hw_params_set_channels(pcm_handle, hwparams,
                m_audio_channels), QString("failed to set channels to %1")
                .arg(m_audio_channels)))
    {
        return false;
    }
    if (AlsaBad(snd_pcm_hw_params_set_rate(pcm_handle, hwparams,
                                           m_audio_sample_rate, 0), QString("failed to set sample rate %1")
                .arg(m_audio_sample_rate)))
    {
        uint rate_num = 0;
        uint rate_den = 0;
        if (!AlsaBad(snd_pcm_hw_params_get_rate_numden(hwparams, &rate_num,
                     &rate_den), "snd_pcm_hw_params_get_rate_numden failed"))
            if (m_audio_sample_rate != (int)(rate_num / rate_den))
                LOG(VB_GENERAL, LOG_ERR, LOC_DEV +
                    QString("device reports sample rate as %1")
                    .arg(rate_num / rate_den));
        return false;
    }
    uint buffer_time = 64000; // 64 msec
    uint period_time = buffer_time / 4;
    if (AlsaBad(snd_pcm_hw_params_set_period_time_near(pcm_handle, hwparams, &period_time, NULL),
                "failed to set period time"))
        return false;
    if (AlsaBad(snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams, &buffer_time, NULL),
                "failed to set buffer time"))
        return false;
    if (AlsaBad(snd_pcm_hw_params_get_period_size(hwparams, &period_size, NULL),
                "failed to get period size"))
        return false;

    if (AlsaBad(snd_pcm_hw_params (pcm_handle, hwparams),
                "failed to set hwparams"))
        return false;

    myth_block_bytes = snd_pcm_frames_to_bytes(pcm_handle, period_size);
    LOG(VB_AUDIO, LOG_INFO, LOC_DEV +
        QString("channels %1, sample rate %2, buffer_time %3 msec, period "
                "size %4").arg(m_audio_channels)
        .arg(m_audio_sample_rate).arg(buffer_time / 1000.0, -1, 'f', 1)
        .arg(period_size));
    LOG(VB_AUDIO, LOG_DEBUG, LOC_DEV + QString("myth block size %1")
        .arg(myth_block_bytes));
    return true;
}