예제 #1
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;
}
예제 #2
0
파일: alsa.c 프로젝트: Amalerd/SoxPlayer
static int select_format(
    sox_encoding_t              * encoding_,
    unsigned                    * nbits_,
    snd_pcm_format_mask_t const * mask,
    int                         * format)
{
  unsigned can_do[NSIZES], i, j, index = (*nbits_ >> 3) - 1, nbits;
  sox_encoding_t encoding = *encoding_;

  for (i = 0; i < NSIZES; ++i) for (can_do[i] = 0, j = 0; j < 2; ++j)
    can_do[i] |= snd_pcm_format_mask_test(mask, formats[j][i]);

  if (index >= NSIZES ||
      (encoding != SOX_ENCODING_SIGN2 && encoding != SOX_ENCODING_UNSIGNED)){
    encoding = SOX_ENCODING_SIGN2;
    index = 2;
  }
  while (!can_do[index]) if (++index == NSIZES)           /* Search up */
    for (--index; !can_do[index];) if (--index >= NSIZES) /* then down */
      return -1;
  nbits = (index + 1) << 3;

  if (encoding == SOX_ENCODING_SIGN2 &&
      !snd_pcm_format_mask_test(mask, formats[0][index]))
    encoding = SOX_ENCODING_UNSIGNED;

  if (*nbits_ != nbits || *encoding_ != encoding) {
    lsx_warn("can't encode %u-bit %s", *nbits_,
        sox_encodings_info[*encoding_].desc);
    *nbits_ = nbits;
    *encoding_ = encoding;
  }
  *format = formats[encoding == SOX_ENCODING_UNSIGNED][index];
  return 0;
}
예제 #3
0
static int select_format(sox_encoding_t * e, unsigned * bits, snd_pcm_format_mask_t const * mask, int * format)
{
    unsigned does[3], i, j, k = (*bits >> 3) - 1;

    if (k > 2 || (*e != SOX_ENCODING_SIGN2 && *e != SOX_ENCODING_UNSIGNED))
        return -1;
    for (i = 0; i < 3; ++i) for (does[i] = 0, j = 0; j < 2; ++j)
            does[i] |= snd_pcm_format_mask_test(mask, encs[j][i]);
    if (!does[k])
        k = 1;
    while (!does[k]) if ((k = (k + 1 ) % 3) == 1)
            return -1;
    *bits = (k + 1) << 3;

    if (*e == SOX_ENCODING_SIGN2 && !snd_pcm_format_mask_test(mask, encs[0][k]))
        *e = SOX_ENCODING_UNSIGNED;
    *format = encs[*e == SOX_ENCODING_UNSIGNED][k];
    return 0;
}
예제 #4
0
static void
as_setup_format_combo(GawSndData *snd)
{
   GtkWidget *combo = snd->w_format;
   snd_pcm_format_t format = snd->sparams->format;
   snd_pcm_t *pcm;
   snd_pcm_hw_params_t *hwparams;
   snd_pcm_format_mask_t *formatMask;
   AsFormatList *p;
   int i ;
   int err;

   for ( i = snd->n_format ; i > 0; i-- ){
      gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (combo), i - 1 );
   }
   snd->n_format = 0;

   snd_pcm_hw_params_alloca(&hwparams);
   snd_pcm_format_mask_alloca(&formatMask);

   err = snd_pcm_open(&pcm, snd->sparams->device_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
   if (  err < 0 ) {
      return;
   }
   err = snd_pcm_hw_params_any(pcm, hwparams);
   if ( err < 0 ) {
      snd_pcm_close(pcm);
      return;
   }
   snd_pcm_hw_params_get_format_mask(hwparams, formatMask);
 
   for( p = as_format_list, i = 0 ; p->name ; p++, i++ ){
      if ( snd_pcm_format_mask_test ( formatMask, p->format ) < 0 ){
	 continue;
      }
      gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), p->name );
//      msg_dbg("as_format %d '%s'", snd->n_format, p->name );
      snd->n_format++;
      if ( p->format == format ) {
	 gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i);
      }
   }
   snd_pcm_close(pcm);
}
예제 #5
0
static int check_linear_format(const snd_pcm_format_mask_t *format_mask, int wid, int sgn, int ed)
{
	int e, s;
	if (! linear_format_widths[wid - 1])
		return SND_PCM_FORMAT_UNKNOWN;
	for (e = 0; e < 2; e++) {
		for (s = 0; s < 2; s++) {
			int pw = ((wid + 7) / 8) * 8;
			for (; pw <= 32; pw += 8) {
				snd_pcm_format_t f;
				f = snd_pcm_build_linear_format(wid, pw, sgn, ed);
				if (f != SND_PCM_FORMAT_UNKNOWN &&
				    snd_pcm_format_mask_test(format_mask, f))
					return f;
			}
			sgn = !sgn;
		}
		ed = !ed;
	}
	return SND_PCM_FORMAT_UNKNOWN;
}
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);
}
예제 #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
/**************************************************************************
 * 			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;
}
예제 #9
0
static snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, const snd_pcm_format_mask_t *format_mask)
{
	int w, w1, u, e;
	snd_pcm_format_t f;
	snd_pcm_format_mask_t lin = { SND_PCM_FMTBIT_LINEAR };
	snd_pcm_format_mask_t fl = {
#ifdef BUILD_PCM_PLUGIN_LFLOAT
		SND_PCM_FMTBIT_FLOAT
#else
		{ 0 }
#endif
	};
	if (snd_pcm_format_mask_test(format_mask, format))
		return format;
	if (!snd_pcm_format_mask_test(&lin, format) &&
	    !snd_pcm_format_mask_test(&fl, format)) {
		unsigned int i;
		switch (format) {
#ifdef BUILD_PCM_PLUGIN_MULAW
		case SND_PCM_FORMAT_MU_LAW:
#endif
#ifdef BUILD_PCM_PLUGIN_ALAW
		case SND_PCM_FORMAT_A_LAW:
#endif
#ifdef BUILD_PCM_PLUGIN_ADPCM
		case SND_PCM_FORMAT_IMA_ADPCM:
#endif
			for (i = 0; i < sizeof(linear_preferred_formats) / sizeof(linear_preferred_formats[0]); ++i) {
				snd_pcm_format_t f = linear_preferred_formats[i];
				if (snd_pcm_format_mask_test(format_mask, f))
					return f;
			}
			/* Fall through */
		default:
			return SND_PCM_FORMAT_UNKNOWN;
		}

	}
	snd_mask_intersect(&lin, format_mask);
	snd_mask_intersect(&fl, format_mask);
	if (snd_mask_empty(&lin) && snd_mask_empty(&fl)) {
#ifdef BUILD_PCM_NONLINEAR
		unsigned int i;
		for (i = 0; i < sizeof(nonlinear_preferred_formats) / sizeof(nonlinear_preferred_formats[0]); ++i) {
			snd_pcm_format_t f = nonlinear_preferred_formats[i];
			if (snd_pcm_format_mask_test(format_mask, f))
				return f;
		}
#endif
		return SND_PCM_FORMAT_UNKNOWN;
	}
#ifdef BUILD_PCM_PLUGIN_LFLOAT
	if (snd_pcm_format_float(format)) {
		if (snd_pcm_format_mask_test(&fl, format)) {
			unsigned int i;
			for (i = 0; i < sizeof(float_preferred_formats) / sizeof(float_preferred_formats[0]); ++i) {
				snd_pcm_format_t f = float_preferred_formats[i];
				if (snd_pcm_format_mask_test(format_mask, f))
					return f;
			}
		}
		w = 32;
		u = 0;
		e = snd_pcm_format_big_endian(format);
	} else
#endif
	if (snd_mask_empty(&lin)) {
#ifdef BUILD_PCM_PLUGIN_LFLOAT
		unsigned int i;
		for (i = 0; i < sizeof(float_preferred_formats) / sizeof(float_preferred_formats[0]); ++i) {
			snd_pcm_format_t f = float_preferred_formats[i];
			if (snd_pcm_format_mask_test(format_mask, f))
				return f;
		}
#endif
		return SND_PCM_FORMAT_UNKNOWN;
	} else {
		w = snd_pcm_format_width(format);
		u = snd_pcm_format_unsigned(format);
		e = snd_pcm_format_big_endian(format);
	}
	for (w1 = w; w1 <= 32; w1++) {
		f = check_linear_format(format_mask, w1, u, e);
		if (f != SND_PCM_FORMAT_UNKNOWN)
			return f;
	}
	for (w1 = w - 1; w1 > 0; w1--) {
		f = check_linear_format(format_mask, w1, u, e);
		if (f != SND_PCM_FORMAT_UNKNOWN)
			return f;
	}
	return SND_PCM_FORMAT_UNKNOWN;
}
예제 #10
0
파일: alsa.cpp 프로젝트: manushanga/vrok
int VPOutPluginAlsa::init(VPlayer *v, VPBuffer *in)
{
    DBG("Alsa:init");
    owner = v;
    bin = in;
    if (snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE) < 0){
        DBG("Alsa:init: failed to open pcm");
        exit(0);
        return -1;
    }
    snd_pcm_sw_params_t *swparams;
    snd_pcm_sw_params_malloc(&swparams);
    snd_pcm_sw_params_current (handle, swparams);
    snd_pcm_sw_params_set_start_threshold (handle, swparams, VPBUFFER_FRAMES - PERIOD_SIZE);
    snd_pcm_sw_params (handle, swparams);
    snd_pcm_sw_params_free(swparams);

    snd_pcm_hw_params_alloca(&params);
    snd_pcm_hw_params_any(handle, params);
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    snd_pcm_format_mask_t *mask;
    snd_pcm_format_mask_alloca(&mask);
    snd_pcm_hw_params_get_format_mask(params, mask);
    if (snd_pcm_format_mask_test(mask, SND_PCM_FORMAT_S32))
    {
        DBG("bit depth is 32");
        snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S32);
        multiplier = (1<<31) -1 ;
        DBG(multiplier);
    }
    else if (snd_pcm_format_mask_test(mask, SND_PCM_FORMAT_S24))
    {
        DBG("bit depth is 24");
        snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24);
        multiplier = (1<<23) -1;
    }
    else if (snd_pcm_format_mask_test(mask, SND_PCM_FORMAT_S16))
    {
        DBG("bit depth is 16");
        snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16);
        multiplier = (1<<15) -1;
    }
    else if (snd_pcm_format_mask_test(mask, SND_PCM_FORMAT_S8))
    {
        DBG("bit depth is 8");
        snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S8);
        multiplier = (1<<7) -1;;
    }

    snd_pcm_hw_params_set_channels(handle, params, bin->chans);

    snd_pcm_hw_params_set_period_size(handle, params, PERIOD_SIZE, 0);

    if (snd_pcm_hw_params(handle, params) < 0) {
        DBG("Alsa:init: failed to set pcm params");
       return -1;
    }

    snd_pcm_hw_params_current(handle, params);
    int dir;
    snd_pcm_hw_params_get_rate(params, &out_srate, &dir);
    in_srate = bin->srate;
    int rerr;
    rs = src_new(SRC_SINC_FASTEST, bin->chans, &rerr);
    if (!rs){
        DBG("SRC error"<<rerr);
        return -1;
    }

    rd.src_ratio = (out_srate*1.0)/(in_srate*1.0);
    out_frames = (VPBUFFER_FRAMES*rd.src_ratio)*2;

    out_buf = (float *)ALIGNED_ALLOC(sizeof(float)*out_frames*bin->chans);
    out_buf_i = (int *)ALIGNED_ALLOC(sizeof(int)*out_frames*bin->chans);

    DBG("target rate "<<out_srate);
    work = true;
    paused = false;
    pause_check = false;

    FULL_MEMORY_BARRIER;
    in_fd = inotify_init();
    if ( in_fd < 0 ) {
        DBG("error initializing inotify, auto pause won't work");
    } else {
        in_wd[0]=inotify_add_watch( in_fd, "/dev/snd/pcmC0D0p", IN_OPEN | IN_CLOSE );
    }
    fcntl(in_fd, F_SETFL, O_NONBLOCK);

    worker = new std::thread((void(*)(void*))worker_run, this);
    worker->high_priority();
    DBG("alsa thread made");
    DBG((void *)VPOutPluginAlsa::check_contention);
    VPEvents::getSingleton()->schedulerAddJob((VPEvents::VPJob) VPOutPluginAlsa::check_contention, this,0);
    return 0;
}