예제 #1
0
파일: player.c 프로젝트: ayoucai/cmus
static inline int sf_need_swap(sample_format_t sf)
{
#ifdef WORDS_BIGENDIAN
	return !sf_get_bigendian(sf);
#else
	return sf_get_bigendian(sf);
#endif
}
예제 #2
0
파일: sndio.c 프로젝트: BG2BKK/cmus
static int sndio_set_sf(sample_format_t sf)
{
	struct sio_par apar;

	sndio_sf = sf;

	sio_initpar(&par);

	par.pchan = sf_get_channels(sndio_sf);
	par.rate = sf_get_rate(sndio_sf);
	sndio_paused = 0;

	if (sf_get_signed(sndio_sf))
		par.sig = 1;
	else
		par.sig = 0;

	if (sf_get_bigendian(sndio_sf))
		par.le = 0;
	else
		par.le = 1;

	switch (sf_get_bits(sndio_sf)) {
	case 16:
		par.bits = 16;
		break;
	case 8:
		par.bits = 8;
		break;
	default:
		return -OP_ERROR_SAMPLE_FORMAT;
	}

	par.appbufsz = par.rate * 300 / 1000;
	apar = par;

	if (!sio_setpar(hdl, &par))
		return -OP_ERROR_INTERNAL;

	if (!sio_getpar(hdl, &par))
		return -OP_ERROR_INTERNAL;

	if (apar.rate != par.rate || apar.pchan != par.pchan ||
	    apar.bits != par.bits || (par.bits > 8 && apar.le != par.le) ||
	    apar.sig != par.sig)
		return -OP_ERROR_INTERNAL;

	sndio_mixer_set_volume(sndio_volume, sndio_volume);

	if (!sio_start(hdl))
		return -OP_ERROR_INTERNAL;

	return OP_ERROR_SUCCESS;
}
예제 #3
0
파일: waveout.c 프로젝트: dodamn/pkg-cmus
static int waveout_open(sample_format_t sf)
{
	WAVEFORMATEX  format;
	int rc, i;

	/* WAVEFORMATEX does not support channels > 2, waveOutWrite() wants little endian signed PCM */
	if (sf_get_bigendian(sf) || !sf_get_signed(sf) || sf_get_channels(sf) > 2) {
		return -OP_ERROR_SAMPLE_FORMAT;
	}

	memset(&format, 0, sizeof(format));
	format.cbSize = sizeof(format);
	format.wFormatTag = WAVE_FORMAT_PCM;
	format.nChannels = sf_get_channels(sf);
	format.nSamplesPerSec = sf_get_rate(sf);
	format.wBitsPerSample = sf_get_bits(sf);
	format.nAvgBytesPerSec = sf_get_second_size(sf);
	format.nBlockAlign = sf_get_frame_size(sf);

	if ((rc = waveOutOpen(&wave_out, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL)) != MMSYSERR_NOERROR) {
		switch (rc) {
		case MMSYSERR_ALLOCATED:
			errno = EBUSY;
			return -OP_ERROR_ERRNO;
		case MMSYSERR_BADDEVICEID:
		case MMSYSERR_NODRIVER:
			errno = ENODEV;
			return -OP_ERROR_ERRNO;
		case MMSYSERR_NOMEM:
			errno = ENOMEM;
			return -OP_ERROR_ERRNO;
		case WAVERR_BADFORMAT:
			return -OP_ERROR_SAMPLE_FORMAT;
		}
		return -OP_ERROR_INTERNAL;
	}

	/* reset buffers */
	for (i = 0; i < buffer_count; i++) {
		buffers[i].dwFlags = 0;
	}
	buffer_idx = 0;
	buffers_free = buffer_count;

	waveout_sf = sf;

	return 0;
}
예제 #4
0
파일: player.c 프로젝트: ayoucai/cmus
static void scale_samples(char *buffer, unsigned int *countp)
{
	unsigned int count = *countp;
	int ch, bits, l, r;

	BUG_ON(scale_pos < consumer_pos);

	if (consumer_pos != scale_pos) {
		unsigned int offs = scale_pos - consumer_pos;

		if (offs >= count)
			return;
		buffer += offs;
		count -= offs;
	}
	scale_pos += count;

	if (replaygain_scale == 1.0 && soft_vol_l == 100 && soft_vol_r == 100)
		return;

	ch = sf_get_channels(buffer_sf);
	bits = sf_get_bits(buffer_sf);
	if (ch != 2 || (bits != 16 && bits != 24 && bits != 32))
		return;

	l = SOFT_VOL_SCALE;
	r = SOFT_VOL_SCALE;
	if (soft_vol && soft_vol_l != 100)
		l = soft_vol_db[soft_vol_l];
	if (soft_vol && soft_vol_r != 100)
		r = soft_vol_db[soft_vol_r];

	l *= replaygain_scale;
	r *= replaygain_scale;

	switch (bits) {
	case 16:
		SCALE_SAMPLES(int16_t, buffer, count, l, r, sf_need_swap(buffer_sf));
		break;
	case 24:
		if (likely(!sf_get_bigendian(buffer_sf)))
			scale_samples_s24le(buffer, count, l, r);
		break;
	case 32:
		SCALE_SAMPLES(int32_t, buffer, count, l, r, sf_need_swap(buffer_sf));
		break;
	}
}
예제 #5
0
파일: roar.c 프로젝트: Brijen/cmus
static int op_roar_open(sample_format_t sf, const channel_position_t *channel_map)
{
    struct roar_audio_info info;
    int ret;

    memset(&info, 0, sizeof(info));

    ROAR_DBG("op_roar_open(*) = ?");

    format = sf;

    info.rate = sf_get_rate(sf);
    info.channels = sf_get_channels(sf);
    info.bits = sf_get_bits(sf);

    if (sf_get_bigendian(sf)) {
        if (sf_get_signed(sf)) {
            info.codec = ROAR_CODEC_PCM_S_BE;
        } else {
            info.codec = ROAR_CODEC_PCM_U_BE;
        }
    } else {
        if (sf_get_signed(sf)) {
            info.codec = ROAR_CODEC_PCM_S_LE;
        } else {
            info.codec = ROAR_CODEC_PCM_U_LE;
        }
    }

    ROAR_DBG("op_roar_open(*) = ?");

    if (roar_libroar_set_server(host) == -1) {
        ROAR_DBG("op_roar_open(*) = ?");

        roar_err_to_errno();
        return -OP_ERROR_ERRNO;
    }

    if ( roar_simple_connect2(&con, NULL, "C* Music Player (cmus)", ROAR_ENUM_FLAG_NONBLOCK, 0) == -1 ) {
        ROAR_DBG("op_roar_open(*) = ?");

        roar_err_to_errno();
        return -OP_ERROR_ERRNO;
    }

    vss = roar_vs_new_from_con(&con, &err);
    if (vss == NULL) {
        ROAR_DBG("op_roar_open(*) = ?");

        roar_disconnect(&con);

        _err_to_errno();
        return -OP_ERROR_ERRNO;
    }

    if (roar_vs_stream(vss, &info, ROAR_DIR_PLAY, &err) == -1) {
        ROAR_DBG("op_roar_open(*) = ?");

        roar_disconnect(&con);

        _err_to_errno();
        return -OP_ERROR_ERRNO;
    }

    ROAR_DBG("op_roar_open(*) = ?");

    if (roar_vs_buffer(vss, 2048*8, &err) == -1) {
        roar_vs_close(vss, ROAR_VS_TRUE, NULL);
        roar_disconnect(&con);
        _err_to_errno();
        return -OP_ERROR_ERRNO;
    }

    ROAR_DBG("op_roar_open(*) = ?");

    ret = _set_role();
    if (ret != 0) {
        roar_vs_close(vss, ROAR_VS_TRUE, NULL);
        roar_disconnect(&con);
        _err_to_errno();
        return ret;
    }

    ROAR_DBG("op_roar_open(*) = ?");

    if (roar_vs_blocking(vss, ROAR_VS_FALSE, &err) == -1) {
        /* FIXME: handle this error */
    }

    ROAR_DBG("op_roar_open(*) = 0");

    return 0;
}
예제 #6
0
파일: oss.c 프로젝트: shawakaze/cmus
static int oss_set_sf(sample_format_t sf)
{
	int tmp, log2_fragment_size, nr_fragments, bytes_per_second;

	oss_reset();
	oss_sf = sf;

#ifdef SNDCTL_DSP_CHANNELS
	tmp = sf_get_channels(oss_sf);
	if (ioctl(oss_fd, SNDCTL_DSP_CHANNELS, &tmp) == -1)
		return -1;
#else
	tmp = sf_get_channels(oss_sf) - 1;
	if (ioctl(oss_fd, SNDCTL_DSP_STEREO, &tmp) == -1)
		return -1;
#endif

	if (sf_get_bits(oss_sf) == 16) {
		if (sf_get_signed(oss_sf)) {
			if (sf_get_bigendian(oss_sf)) {
				tmp = AFMT_S16_BE;
			} else {
				tmp = AFMT_S16_LE;
			}
		} else {
			if (sf_get_bigendian(oss_sf)) {
				tmp = AFMT_U16_BE;
			} else {
				tmp = AFMT_U16_LE;
			}
		}
	} else if (sf_get_bits(oss_sf) == 8) {
		if (sf_get_signed(oss_sf)) {
			tmp = AFMT_S8;
		} else {
			tmp = AFMT_U8;
		}
	} else if (sf_get_bits(oss_sf) == 32 && sf_get_signed(oss_sf)) {
		if (sf_get_bigendian(oss_sf)) {
			tmp = AFMT_S32_BE;
		} else {
			tmp = AFMT_S32_LE;
		}
	} else if (sf_get_bits(oss_sf) == 24 && sf_get_signed(oss_sf) && !sf_get_bigendian(oss_sf)) {
		tmp = AFMT_S24_PACKED;
	} else {
		d_print("unsupported sample format: %c%u_%s\n",
			sf_get_signed(oss_sf) ? 'S' : 'U', sf_get_bits(oss_sf),
			sf_get_bigendian(oss_sf) ? "BE" : "LE");
		return -1;
	}
	if (ioctl(oss_fd, SNDCTL_DSP_SAMPLESIZE, &tmp) == -1)
		return -1;

	tmp = sf_get_rate(oss_sf);
	if (ioctl(oss_fd, SNDCTL_DSP_SPEED, &tmp) == -1)
		return -1;

	bytes_per_second = sf_get_second_size(oss_sf);
	log2_fragment_size = 0;
	while (1 << log2_fragment_size < bytes_per_second / 25)
		log2_fragment_size++;
	log2_fragment_size--;
	nr_fragments = 32;

	/* bits 0..15 = size of fragment, 16..31 = log2(number of fragments) */
	tmp = (nr_fragments << 16) + log2_fragment_size;
	if (ioctl(oss_fd, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
		return -1;
	return 0;
}