Esempio n. 1
0
File: jack.c Progetto: jolange/cmus
static int op_jack_open(sample_format_t sf, const channel_position_t *cm)
{
	sample_format = sf;

	if (fail) {
		/* jack went away so lets see if we can recover */
		if (client != NULL) {
			op_jack_exit();
		}
		if (op_jack_init() != OP_ERROR_SUCCESS) {
			return -OP_ERROR_INTERNAL;
		}
	}

	if (cm == NULL) {
		d_print("no channel_map\n");
		return -OP_ERROR_NOT_SUPPORTED;
	}
	channel_map = cm;

#ifdef HAVE_SAMPLERATE
	op_jack_reset_src();
	resample_ratio = (float) jack_sample_rate / (float) sf_get_rate(sf);
#else
	if (jack_sample_rate != sf_get_rate(sf)) {
		d_print("jack sample rate of %d does not match %d\n", jack_get_sample_rate(client), sf_get_rate(sf));
		return -OP_ERROR_SAMPLE_FORMAT;
	}
#endif

	if (sf_get_channels(sf) < CHANNELS) {
		d_print("%d channels not supported\n", sf_get_channels(sf));
		return -OP_ERROR_SAMPLE_FORMAT;
	}

	int bits = sf_get_bits(sf);

	if (bits == 16) {
		sample_bytes = 2;
		read_sample = sf_get_signed(sf) ? &read_sample_le16 : &read_sample_le16u;
	} else if (bits == 24) {
		sample_bytes = 3;
		read_sample = sf_get_signed(sf) ? &read_sample_le24 : &read_sample_le24u;
	} else if (bits == 32) {
		sample_bytes = 4;
		read_sample = sf_get_signed(sf) ? &read_sample_le32 : &read_sample_le32u;
	} else {
		d_print("%d bits not supported\n", sf_get_bits(sf));
		return -OP_ERROR_SAMPLE_FORMAT;
	}

	paused = false;
	return OP_ERROR_SUCCESS;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
static int change_sf(int drop)
{
	int old_sf = buffer_sf;
	CHANNEL_MAP(old_channel_map);
	channel_map_copy(old_channel_map, buffer_channel_map);

	set_buffer_sf();
	if (buffer_sf != old_sf || !channel_map_equal(buffer_channel_map, old_channel_map, sf_get_channels(buffer_sf))) {
		/* reopen */
		int rc;

		if (drop)
			op_drop();
		op_close();
		rc = op_open(buffer_sf, buffer_channel_map);
		if (rc) {
			player_op_error(rc, "opening audio device");
			__consumer_status_update(CS_STOPPED);
			__producer_stop();
			return rc;
		}
	} else if (consumer_status == CS_PAUSED) {
		op_drop();
		op_unpause();
	}
	__consumer_status_update(CS_PLAYING);
	return 0;
}
Esempio n. 4
0
File: sndio.c Progetto: 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;
}
Esempio n. 5
0
static void set_buffer_sf(void)
{
	buffer_sf = ip_get_sf(ip);
	ip_get_channel_map(ip, buffer_channel_map);

	/* ip_read converts samples to this format */
	if (sf_get_channels(buffer_sf) <= 2 && sf_get_bits(buffer_sf) <= 16) {
		buffer_sf &= SF_RATE_MASK;
		buffer_sf |= sf_channels(2) | sf_bits(16) | sf_signed(1);
		buffer_sf |= sf_host_endian();
		channel_map_init_stereo(buffer_channel_map);
	}
}
Esempio n. 6
0
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;
	}
}
Esempio n. 7
0
File: arts.c Progetto: jolange/cmus
static int op_arts_open(sample_format_t sf, const channel_position_t *channel_map)
{
	int buffer_time, server_latency, total_latency;
	int blocking;

	arts_sf = sf;
	arts_stream = arts_play_stream(sf_get_rate(arts_sf), sf_get_bits(arts_sf),
			sf_get_channels(arts_sf), "cmus");
	blocking = arts_stream_set(arts_stream, ARTS_P_BLOCKING, 0);
	if (blocking) {
	}
	arts_buffer_size = arts_stream_get(arts_stream, ARTS_P_BUFFER_SIZE);
	if (arts_buffer_size < 0) {
	}
	buffer_time = arts_stream_get(arts_stream, ARTS_P_BUFFER_TIME);
	server_latency = arts_stream_get(arts_stream, ARTS_P_SERVER_LATENCY);
	total_latency = arts_stream_get(arts_stream, ARTS_P_TOTAL_LATENCY);
	d_print("buffer_time: %d\n", buffer_time);
	d_print("server_latency: %d\n", server_latency);
	d_print("total_latency: %d\n", total_latency);
	return 0;
}
Esempio n. 8
0
File: roar.c Progetto: 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;
}
Esempio n. 9
0
			 0, NULL, layout_size, layout);
	if (err != noErr)
		d_print("Cannot set the channel layout successfully.\n");
	free(layout);
}


static AudioStreamBasicDescription coreaudio_fill_format_description(sample_format_t sf)
{
	AudioStreamBasicDescription desc = {
		.mSampleRate       = (Float64)sf_get_rate(sf),
		.mFormatID         = kAudioFormatLinearPCM,
		.mFormatFlags      = kAudioFormatFlagIsPacked,
		.mBytesPerPacket   = sf_get_frame_size(sf),
		.mFramesPerPacket  = 1,
		.mChannelsPerFrame = sf_get_channels(sf),
		.mBitsPerChannel   = sf_get_bits(sf),
		.mBytesPerFrame    = sf_get_frame_size(sf),
	};

	d_print("Bits:%d\n", sf_get_bits(sf));
	if (sf_get_bigendian(sf))
		desc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
	if (sf_get_signed(sf))
		desc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;

	return desc;
}

static void coreaudio_sync_device_sample_rate(AudioDeviceID dev_id, AudioStreamBasicDescription desc)
{
Esempio n. 10
0
File: jack.c Progetto: BG2BKK/cmus
static int op_jack_write(const char *buffer, int count)
{
	if (fail) {
		op_jack_exit();
		return -OP_ERROR_INTERNAL;
	}

	if (!drop_done) {
		return 0;
	}

	int frame_size = sf_get_frame_size(sample_format);
	int channels = sf_get_channels(sample_format);
	size_t frames = count / frame_size;

	/* since this is the only place where the ringbuffers get
	 * written, available space will only grow, therefore frames_min
	 * is safe.
	 */
	size_t frames_min = SIZE_MAX;
	for (int c = 0; c < CHANNELS; c++) {
		size_t frames_available = jack_ringbuffer_write_space(ringbuffer[c]) / sizeof(jack_default_audio_sample_t);
		if (frames_available < frames_min) {
			frames_min = frames_available;
		}
	}

	if (frames > frames_min) {
		frames = frames_min;
	}

	jack_default_audio_sample_t buf[CHANNELS][buffer_size];

	/* demux and convert to float */
	for (int pos = 0; pos < count; ) {
		int frame = pos / frame_size;
		for (int c = 0; c < channels; c++) {
			int idx = pos + c * sample_bytes;
			/* for now, only 2 channels and mono are supported */
			if (channel_map[c] == CHANNEL_POSITION_LEFT || channel_map[c] == CHANNEL_POSITION_MONO) {
				buf[0][frame] = read_sample(&buffer[idx]);
			} else if (channel_map[c] == CHANNEL_POSITION_RIGHT || channel_map[c] == CHANNEL_POSITION_MONO) {
				buf[1][frame] = read_sample(&buffer[idx]);
			}
		}
		pos += frame_size;
	}

#ifdef HAVE_SAMPLERATE
	if (resample_ratio > 1.01f || resample_ratio < 0.99) {
		jack_default_audio_sample_t converted[buffer_size];
		SRC_DATA src_data;
		for (int c = 0; c < CHANNELS; c++) {
			src_data.data_in = buf[c];
			src_data.data_out = converted;
			src_data.input_frames = frames;
			src_data.output_frames = frames_min;
			src_data.src_ratio = resample_ratio;
			src_data.end_of_input = 0;

			int err = src_process(src_state[c], &src_data);
			if (err) {
				d_print("libsamplerate err %s\n", src_strerror(err));
			}

			int byte_length = src_data.output_frames_gen * sizeof(jack_default_audio_sample_t);
			jack_ringbuffer_write(ringbuffer[c], (const char*) converted, byte_length);
		}
		return src_data.input_frames_used * frame_size;
	} else {
#endif
		int byte_length = frames * sizeof(jack_default_audio_sample_t);
		for (int c = 0; c < CHANNELS; c++) {
			jack_ringbuffer_write(ringbuffer[c], (const char*) buf[c], byte_length);
		}

		return frames * frame_size;
#ifdef HAVE_SAMPLERATE
	}
#endif
}
Esempio n. 11
0
File: oss.c Progetto: 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;
}