⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
📖 第 1 页 / 共 2 页
字号:
		*outptr++ =					\			(sample_type)				\			((inptr[((x1 >> 12) << 1) + 1] *	\			  ((1<<12) - frac) +			\			  inptr[(((x1 >> 12) + 1) << 1) + 1] *	\			  frac) >> 12);				\		x += delta;					\	}							\	if (NOT_NATIVE_ENDIAN)					\		swap_endian(nbuffer, nlen);			\	w = write_all(fd, nbuffer, nlen);			\} while (0)#define RESAMPLE_MONO(sample_type)				\do {								\	const gint shift = sizeof (sample_type) - 1;		\        gint i, x, delta, in_samples, out_samples;		\	sample_type *inptr = (sample_type *)ob, *outptr;	\	guint nlen = (((length >> shift) * espeed) / speed);	\	if (nlen == 0)						\		break;						\	nlen <<= shift;						\	if (NOT_NATIVE_ENDIAN)					\		swap_endian(ob, length);			\	if(nlen > nbuffer_size)					\	{							\		nbuffer = g_realloc(nbuffer, nlen);		\		nbuffer_size = nlen;				\	}							\	outptr = (sample_type *)nbuffer;			\	in_samples = length >> shift;				\        out_samples = nlen >> shift;				\	delta = ((length >> shift) << 12) / out_samples;	\	for (x = 0, i = 0; i < out_samples; i++)		\	{							\		gint x1, frac;					\		x1 = (x >> 12) << 12;				\		frac = x - x1;					\		*outptr++ =					\			(sample_type)				\			((inptr[x1 >> 12] * ((1<<12) - frac) +	\			  inptr[(x1 >> 12) + 1] * frac) >> 12);	\		x += delta;					\	}							\	if (NOT_NATIVE_ENDIAN)					\		swap_endian(nbuffer, nlen);			\	w = write_all(fd, nbuffer, nlen);			\} while (0)static gint oss_downsample(gpointer ob, guint length, guint speed, guint espeed){	guint w = 0;	static gpointer nbuffer = NULL;	static gint nbuffer_size = 0;	switch (output.format.oss)	{		case AFMT_S16_BE:		case AFMT_S16_LE:			if (output.channels == 2)				RESAMPLE_STEREO(gint16);			else				RESAMPLE_MONO(gint16);			break;		case AFMT_U16_BE:		case AFMT_U16_LE:			if (output.channels == 2)				RESAMPLE_STEREO(guint16);			else				RESAMPLE_MONO(guint16);			break;		case AFMT_S8:			if (output.channels == 2)				RESAMPLE_STEREO(gint8);			else				RESAMPLE_MONO(gint8);			break;		case AFMT_U8:			if (output.channels == 2)				RESAMPLE_STEREO(guint8);			else				RESAMPLE_MONO(guint8);			break;	}	return w;}void oss_write(gpointer ptr, int length){	int cnt, off = 0;	if (!realtime)	{		remove_prebuffer = FALSE;		written += length;		while (length > 0)		{			cnt = MIN(length, buffer_size - wr_index);			memcpy(buffer + wr_index, (char *)ptr + off, cnt);			wr_index = (wr_index + cnt) % buffer_size;			length -= cnt;			off += cnt;		}	}	else	{		if (paused)			return;		oss_write_audio(ptr, length);		written += length;	}}void oss_close(void){	if (!going)		return;	going = 0;	if (!realtime)		pthread_join(buffer_thread, NULL);	else	{		ioctl(fd, SNDCTL_DSP_RESET, 0);		close(fd);	}	g_free(device_name);	oss_free_convert_buffer();	wr_index = 0;	rd_index = 0;}void oss_flush(gint time){	if (!realtime)	{		flush = time;		while (flush != -1)			xmms_usleep(10000);	}	else	{		ioctl(fd, SNDCTL_DSP_RESET, 0);		close(fd);		fd = open(device_name, O_WRONLY);		oss_set_audio_params();		output_time_offset = time;		written = ((guint64)time * input.bps) / 1000;		output_bytes = 0;	}}void oss_pause(short p){	if (!realtime)	{		if (p == TRUE)			do_pause = TRUE;		else			unpause = TRUE;	}	else		paused = p;}void *oss_loop(void *arg){	gint length, cnt;	fd_set set;	struct timeval tv;	while (going)	{		if (oss_used() > prebuffer_size)			prebuffer = FALSE;		if (oss_used() > 0 && !paused && !prebuffer)		{			tv.tv_sec = 0;			tv.tv_usec = 10000;			FD_ZERO(&set);			FD_SET(fd, &set);			if(!select_works || (select(fd + 1, NULL, &set, NULL, &tv) > 0))			{				length = MIN(blk_size, oss_used());				while (length > 0)				{					cnt = MIN(length,buffer_size-rd_index);					oss_write_audio(buffer + rd_index, cnt);					rd_index=(rd_index+cnt)%buffer_size;					length-=cnt;								}				if (!oss_used())					ioctl(fd, SNDCTL_DSP_POST, 0);			}		}		else			xmms_usleep(10000);		oss_calc_device_buffer_used();		if (do_pause && !paused)		{			do_pause = FALSE;			paused = TRUE;			/*			 * We lose some data here that is sent to the			 * soundcard, but not yet played.  I don't			 * think this is worth fixing.			 */			ioctl(fd, SNDCTL_DSP_RESET, 0);		}		else if (unpause && paused)		{			unpause = FALSE;			close(fd);			fd = open(device_name, O_WRONLY);			oss_set_audio_params();			paused = FALSE;		}		if (flush != -1)		{			/*			 * This close and open is a work around of a			 * bug that exists in some drivers which cause			 * the driver to get fucked up by a reset			 */			ioctl(fd, SNDCTL_DSP_RESET, 0);			close(fd);			fd = open(device_name, O_WRONLY);			oss_set_audio_params();			output_time_offset = flush;			written = ((guint64)flush * input.bps) / 1000;			rd_index = wr_index = output_bytes = 0;			flush = -1;			prebuffer = TRUE;		}	}	ioctl(fd, SNDCTL_DSP_RESET, 0);	close(fd);	g_free(buffer);	pthread_exit(NULL);}void oss_set_audio_params(void){	int frag, stereo, ret;	struct timeval tv;	fd_set set;	ioctl(fd, SNDCTL_DSP_RESET, 0);	frag = (NFRAGS << 16) | fragsize;	ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &frag);	/*	 * Set the stream format.  This ioctl() might fail, but should	 * return a format that works if it does.	 */	ioctl(fd, SNDCTL_DSP_SETFMT, &output.format.oss);	if (ioctl(fd, SNDCTL_DSP_SETFMT, &output.format.oss) == -1)		g_warning("SNDCTL_DSP_SETFMT ioctl failed: %s",			  strerror(errno));	stereo = output.channels - 1;	ioctl(fd, SNDCTL_DSP_STEREO, &stereo);	output.channels = stereo + 1;	oss_stereo_convert_func = oss_get_stereo_convert_func(output.channels,							      effect.channels);		if (ioctl(fd, SNDCTL_DSP_SPEED, &output.frequency) == -1)		g_warning("SNDCTL_DSP_SPEED ioctl failed: %s", strerror(errno));	if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &blk_size) == -1)		blk_size = 1L << fragsize;	oss_convert_func =		oss_get_convert_func(output.format.oss,				     oss_get_format(effect.format.xmms));	/*	 * Stupid hack to find out if the driver support selects, some	 * drivers won't work properly without a select and some won't	 * work with a select :/	 */		tv.tv_sec = 0;	tv.tv_usec = 50000;	FD_ZERO(&set);	FD_SET(fd, &set);	ret = select(fd + 1, NULL, &set, NULL, &tv);	if (ret > 0)		select_works = TRUE;	else		select_works = FALSE;}gint oss_open(AFormat fmt, gint rate, gint nch){	if (oss_cfg.use_alt_audio_device && oss_cfg.alt_audio_device)		device_name = g_strdup(oss_cfg.alt_audio_device);	else	{		if (oss_cfg.audio_device > 0)			device_name = g_strdup_printf("%s%d", DEV_DSP, oss_cfg.audio_device);		else			device_name = g_strdup(DEV_DSP);	}	fd = open(device_name, O_WRONLY);	if (fd == -1)	{		g_warning("oss_open(): Failed to open audio device (%s): %s",			  device_name, strerror(errno));		g_free(device_name);		return 0;	}	input.format.xmms = fmt;	input.frequency = rate;	input.channels = nch;	input.bps = oss_calc_bitrate(oss_get_format(fmt), rate, nch);	oss_setup_format(fmt, rate, nch);		realtime = xmms_check_realtime_priority();		if(!realtime)	{		buffer_size = (oss_cfg.buffer_size * input.bps) / 1000;		if (buffer_size < 8192)			buffer_size = 8192;		prebuffer_size = (buffer_size * oss_cfg.prebuffer) / 100;		if (buffer_size - prebuffer_size < 4096)			prebuffer_size = buffer_size - 4096;		buffer_size += device_buffer_size;		buffer = g_malloc0(buffer_size);	}	flush = -1;	prebuffer = TRUE;	wr_index = rd_index = output_time_offset = written = output_bytes = 0;	paused = FALSE;	do_pause = FALSE;	unpause = FALSE;	remove_prebuffer = FALSE;	going = 1;	if (!realtime)		pthread_create(&buffer_thread, NULL, oss_loop, NULL);	return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -