コード例 #1
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;
}
コード例 #2
0
ファイル: alsa_player.c プロジェクト: 5hanth/dhvani-tts
static void set_params(void)
{
	snd_pcm_hw_params_t *params;
	snd_pcm_sw_params_t *swparams;
	snd_pcm_uframes_t buffer_size;
	int err;
	size_t n;
	unsigned int rate;
	snd_pcm_uframes_t start_threshold, stop_threshold;
	snd_pcm_hw_params_alloca(&params);
	snd_pcm_sw_params_alloca(&swparams);
	err = snd_pcm_hw_params_any(handle, params);
	if (err < 0) {
		error("Broken configuration for this PCM: no configurations available");
		exit(EXIT_FAILURE);
	}
	if (mmap_flag) {
		snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
		snd_pcm_access_mask_none(mask);
		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
		err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
	} else if (interleaved)
		err = snd_pcm_hw_params_set_access(handle, params,
						   SND_PCM_ACCESS_RW_INTERLEAVED);
	else
		err = snd_pcm_hw_params_set_access(handle, params,
						   SND_PCM_ACCESS_RW_NONINTERLEAVED);
	if (err < 0) {
		error("Access type not available");
		exit(EXIT_FAILURE);
	}
	err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
	if (err < 0) {
		error("Sample format non available");
		exit(EXIT_FAILURE);
	}
	err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
	if (err < 0) {
		error("Channels count non available");
		exit(EXIT_FAILURE);
	}

#if 0
	err = snd_pcm_hw_params_set_periods_min(handle, params, 2);
	assert(err >= 0);
#endif
	rate = hwparams.rate;
	err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);
	assert(err >= 0);
	if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) {
		if (!quiet_mode) {
			char plugex[64];
			const char *pcmname = snd_pcm_name(handle);
			fprintf(stderr, "Warning: rate is not accurate (requested = %iHz, got = %iHz)\n", rate, hwparams.rate);
			if (! pcmname || strchr(snd_pcm_name(handle), ':'))
				*plugex = 0;
			else
				snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",
					 snd_pcm_name(handle));
			fprintf(stderr, "         please, try the plug plugin %s\n",
				plugex);
		}
	}
	rate = hwparams.rate;
	if (buffer_time == 0 && buffer_frames == 0) {
		err = snd_pcm_hw_params_get_buffer_time_max(params,
							    &buffer_time, 0);
		assert(err >= 0);
		if (buffer_time > 500000)
			buffer_time = 500000;
	}
	if (period_time == 0 && period_frames == 0) {
		if (buffer_time > 0)
			period_time = buffer_time / 4;
		else
			period_frames = buffer_frames / 4;
	}
	if (period_time > 0)
		err = snd_pcm_hw_params_set_period_time_near(handle, params,
							     &period_time, 0);
	else
		err = snd_pcm_hw_params_set_period_size_near(handle, params,
							     &period_frames, 0);
	assert(err >= 0);
	if (buffer_time > 0) {
		err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
							     &buffer_time, 0);
	} else {
		err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
							     &buffer_frames);
	}
	assert(err >= 0);
	err = snd_pcm_hw_params(handle, params);
	if (err < 0) {
		error("Unable to install hw params:");
		snd_pcm_hw_params_dump(params, log);
		exit(EXIT_FAILURE);
	}
	snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
	snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
	if (chunk_size == buffer_size) {
		error("Can't use period equal to buffer size (%lu == %lu)",
		      chunk_size, buffer_size);
		exit(EXIT_FAILURE);
	}
	snd_pcm_sw_params_current(handle, swparams);
	if (avail_min < 0)
		n = chunk_size;
	else
		n = (double) rate * avail_min / 1000000;
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
	if (err < 0) {
		error("Setting sw params failed\n");
	}

	/* round up to closest transfer boundary */
	n = buffer_size;
	if (start_delay <= 0) {
		start_threshold = n + (double) rate * start_delay / 1000000;
	} else
		start_threshold = (double) rate * start_delay / 1000000;
	if (start_threshold < 1)
		start_threshold = 1;
	if (start_threshold > n)
		start_threshold = n;
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
	assert(err >= 0);
	if (stop_delay <= 0) 
		stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
	else
		stop_threshold = (double) rate * stop_delay / 1000000;
	err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
	assert(err >= 0);

	if (snd_pcm_sw_params(handle, swparams) < 0) {
		error("unable to install sw params:");
		snd_pcm_sw_params_dump(swparams, log);
		exit(EXIT_FAILURE);
	}

	if (verbose)
		snd_pcm_dump(handle, log);

	bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
	bits_per_frame = bits_per_sample * hwparams.channels;
	chunk_bytes = chunk_size * bits_per_frame / 8;
	audiobuf = realloc(audiobuf, chunk_bytes);
	if (audiobuf == NULL) {
		error("not enough memory");
		exit(EXIT_FAILURE);
	}
	// fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);

	/* stereo VU-meter isn't always available... */
	if (vumeter == VUMETER_STEREO) {
		if (hwparams.channels != 2 || !interleaved || verbose > 2)
			vumeter = VUMETER_MONO;
	}

	/* show mmap buffer arragment */
	if (mmap_flag && verbose) {
		const snd_pcm_channel_area_t *areas;
		snd_pcm_uframes_t offset;
		int i;
		err = snd_pcm_mmap_begin(handle, &areas, &offset, &chunk_size);
		if (err < 0) {
			error("snd_pcm_mmap_begin problem: %s", snd_strerror(err));
			exit(EXIT_FAILURE);
		}
		for (i = 0; i < hwparams.channels; i++)
			fprintf(stderr, "mmap_area[%i] = %p,%u,%u (%u)\n", i, areas[i].addr, areas[i].first, areas[i].step, snd_pcm_format_physical_width(hwparams.format));
		/* not required, but for sure */
		snd_pcm_mmap_commit(handle, offset, 0);
	}

	buffer_frames = buffer_size;	/* for position test */
}
コード例 #3
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;
}