Exemple #1
0
static int setup(sox_format_t * ft)
{
  priv_t                 * p = (priv_t *)ft->priv;
  snd_pcm_hw_params_t    * params = NULL;
  snd_pcm_format_mask_t  * mask = NULL;
  snd_pcm_uframes_t      min, max;
  unsigned               n;
  int                    err;

  _(snd_pcm_open, (&p->pcm, ft->filename, ft->mode == 'r'? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, 0));
  _(snd_pcm_hw_params_malloc, (&params));
  _(snd_pcm_hw_params_any, (p->pcm, params));
#if SND_LIB_VERSION >= 0x010009               /* Disable alsa-lib resampling: */
  _(snd_pcm_hw_params_set_rate_resample, (p->pcm, params, 0));
#endif
  _(snd_pcm_hw_params_set_access, (p->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED));

  _(snd_pcm_format_mask_malloc, (&mask));           /* Set format: */
  snd_pcm_hw_params_get_format_mask(params, mask);
  _(select_format, (&ft->encoding.encoding, &ft->encoding.bits_per_sample, mask, &p->format));
  _(snd_pcm_hw_params_set_format, (p->pcm, params, p->format));
  snd_pcm_format_mask_free(mask), mask = NULL;

  n = ft->signal.rate;                              /* Set rate: */
  _(snd_pcm_hw_params_set_rate_near, (p->pcm, params, &n, 0));
  ft->signal.rate = n;

  n = ft->signal.channels;                          /* Set channels: */
  _(snd_pcm_hw_params_set_channels_near, (p->pcm, params, &n));
  ft->signal.channels = n;

  /* Set buf_len > > sox_globals.bufsiz for no underrun: */
  p->buf_len = sox_globals.bufsiz * 8 / NBYTES / ft->signal.channels;
  _(snd_pcm_hw_params_get_buffer_size_min, (params, &min));
  _(snd_pcm_hw_params_get_buffer_size_max, (params, &max));
  p->period = range_limit(p->buf_len, min, max) / 8;
  p->buf_len = p->period * 8;
  _(snd_pcm_hw_params_set_period_size_near, (p->pcm, params, &p->period, 0));
  _(snd_pcm_hw_params_set_buffer_size_near, (p->pcm, params, &p->buf_len));
  if (p->period * 2 > p->buf_len) {
    lsx_fail_errno(ft, SOX_EPERM, "buffer too small");
    goto error;
  }

  _(snd_pcm_hw_params, (p->pcm, params));           /* Configure ALSA */
  snd_pcm_hw_params_free(params), params = NULL;
  _(snd_pcm_prepare, (p->pcm));
  p->buf_len *= ft->signal.channels;                /* No longer in `frames' */
  p->buf = lsx_malloc(p->buf_len * NBYTES);
  return SOX_SUCCESS;

error:
  if (mask) snd_pcm_format_mask_free(mask);
  if (params) snd_pcm_hw_params_free(params);
  return SOX_EOF;
}
Exemple #2
0
static GstCaps *
gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params,
    GstCaps * in_caps)
{
  snd_pcm_format_mask_t *mask;
  GstStructure *s;
  GstCaps *caps;
  gint i;

  snd_pcm_format_mask_malloc (&mask);
  snd_pcm_hw_params_get_format_mask (hw_params, mask);

  caps = gst_caps_new_empty ();

  for (i = 0; i < gst_caps_get_size (in_caps); ++i) {
    GstStructure *scopy;
    gint w, width = 0, depth = 0;

    s = gst_caps_get_structure (in_caps, i);
    if (!gst_structure_has_name (s, "audio/x-raw-int")) {
      GST_DEBUG_OBJECT (obj, "skipping non-int format");
      continue;
    }
    if (!gst_structure_get_int (s, "width", &width) ||
        !gst_structure_get_int (s, "depth", &depth))
      continue;
    if (width == 0 || (width % 8) != 0)
      continue;                 /* Only full byte widths are valid */
    for (w = 0; w < G_N_ELEMENTS (pcmformats); w++)
      if (pcmformats[w].width == width && pcmformats[w].depth == depth)
        break;
    if (w == G_N_ELEMENTS (pcmformats))
      continue;                 /* Unknown format */

    if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) &&
        snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
      /* template contains { true, false } or just one, leave it as it is */
      scopy = gst_structure_copy (s);
    } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) {
      scopy = gst_structure_copy (s);
      gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
    } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) {
      scopy = gst_structure_copy (s);
      gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
    } else {
      scopy = NULL;
    }
    if (scopy) {
      if (width > 8) {
        /* TODO: proper endianness detection, for now it's CPU endianness only */
        gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
      }
      gst_caps_append_structure (caps, scopy);
    }
  }

  snd_pcm_format_mask_free (mask);
  gst_caps_unref (in_caps);
  return caps;
}
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);
}
Exemple #4
0
/* 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;
}