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

📄 audio.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Get the audio info */	ioctl(audiofd, AUDIO_GETINFO, &adinfo);	/* We should be playing */	playing = TRUE;	/* NOTE: What is flush for? */	flush = -1;	/* We aren't paused */	paused = FALSE;	/* We're open */	aopen = TRUE;	prebuffer = TRUE;	remove_prebuffer = FALSE;	/* We're at the beginning */	time_offset = 0;	byte_offset = 0;	audio_scount = 0;	return 0;}void abuffer_shutdown(void){	if (audiofd >= 0)	{		/* Flush out the queue */		if (abuffer_used() > 0)			ioctl(audiofd, I_FLUSH, FLUSHW);		/* Close the stream */		close(audiofd);		audiofd = -2;	}	/* We're closed */	aopen = FALSE;	/* Free the buffer */	g_free(buffer_ptr);	buffer_ptr = buffer_end = buffer_read = buffer_write = NULL;}void * abuffer_loop(void *arg){	gint length, bdiff = paused;	while (playing)	{		if (abuffer_used() > prebuffer_size)			prebuffer = FALSE;		/* If pause has changed status, go ahead and do it */		if (adinfo.play.pause ^ paused)		{			audio_info_t info;			/* Make the structure harmless */			AUDIO_INITINFO(&info);			/* Set the pause */			info.play.pause = paused;			/* Set the option */			ioctl(audiofd, AUDIO_SETINFO, &info);			/* Readback the new data */			ioctl(audiofd, AUDIO_GETINFO, &adinfo);		}		/* If we're not paused and have data, send it */		if (abuffer_used() > 0 && !paused && !prebuffer)		{			/* we have something in the buffer and we're not paused */			length = MIN(SUN_AUDIO_CACHE, abuffer_used()); 			bdiff = buffer_end - buffer_read;			/* Write out the buffer */			if (bdiff < length)			{				audio_play(buffer_read, bdiff);				audio_play(buffer_ptr, length - bdiff);				pthread_mutex_lock(&buflock);				buffer_read = buffer_ptr + length - bdiff;				pthread_mutex_unlock(&buflock);			}			else			{				audio_play(buffer_read, length);				pthread_mutex_lock(&buflock);				buffer_read += length;				pthread_mutex_unlock(&buflock);			}		}		else if (flush != -1)		{			audio_info_t info;			AUDIO_INITINFO(&info);			info.play.pause = 1;			ioctl(audiofd, AUDIO_SETINFO, &info);            			/* Flush out the queue */                        /* Yes this is voodoo magic. On my box, this works.                           But, if I remove the calls to xmms_usleep(), the                           I_FLUSH ioctl puts the audio into a screwy state                           about a quarter of the time. */			xmms_usleep(10000);			ioctl(audiofd, I_FLUSH, FLUSHW);			xmms_usleep(10000);			/* Make the structure harmless */			AUDIO_INITINFO(&info);			/* Make sure we clear the statistics */			info.play.samples = 0;			info.play.pause = 0;			info.play.eof = 0;			info.play.error = 0;			ioctl(audiofd, AUDIO_SETINFO, &info);			ioctl(audiofd, AUDIO_GETINFO, &adinfo);			audio_scount = 0;			/* Force the time and byte offsets */			time_offset = flush;			byte_offset = ((double)flush * stream_attrs.bps / 1000);            			/* Reset the buffers */			buffer_write = buffer_read = buffer_ptr;            			/* Finish the flush */			flush = -1;		}		else		{			xmms_usleep(10000);		}	}	/* Shutdown the buffer */	abuffer_shutdown();	return(NULL);}void abuffer_set_audio_params(void){	audio_info_t info;	if (audiofd >= 0)	{		/* Make the audio info structure harmless */		AUDIO_INITINFO(&info);		/* Fill out our attributes */		info.play.sample_rate = stream_attrs.sample_rate;		info.play.channels = stream_attrs.channels;		info.play.precision = stream_attrs.output_precision;		info.play.encoding = AUDIO_ENCODING_LINEAR;		if (sun_cfg.channel_flags)			info.play.port = sun_cfg.channel_flags;		/* Make sure we're not muted */		info.output_muted = 0;			/* Set input audio data encoding for CD */		info.record.sample_rate = 44100;		info.record.channels = 2;		info.record.precision = 16;		info.record.encoding = AUDIO_ENCODING_LINEAR;			/* Set the info */		if (ioctl(audiofd, AUDIO_SETINFO, &info) == -1)		{			perror ("xmms: could not set audio params");		}		else		{			ioctl(audiofd, AUDIO_GETINFO, &adinfo);		}	}}/* This function sets the parameters for endian-ness and signed status *//* note that for precision=8 we set endianness to be native for speed in *//* dsp_memcpy */gint abuffer_open(AFormat fmt, gint rate, gint nch){	int audiofd;	struct audio_device aud_dev;	char *ctl_dev;	input_format = fmt;	switch (fmt)	{		case FMT_U8:		case FMT_S8:			stream_attrs.precision = 8;			break;		case FMT_U16_LE:		case FMT_U16_BE:		case FMT_U16_NE:		case FMT_S16_LE:		case FMT_S16_BE:		case FMT_S16_NE:			stream_attrs.precision = 16;			break;	}	switch (fmt)	{		case FMT_S8:		case FMT_S16_LE:		case FMT_S16_BE:		case FMT_S16_NE:			stream_attrs.is_signed = TRUE;			break;		case FMT_U8:		case FMT_U16_LE:		case FMT_U16_BE:		case FMT_U16_NE:			stream_attrs.is_signed = FALSE;			break;	}	switch (fmt)	{		case FMT_S8:		case FMT_U8:		case FMT_S16_NE:		case FMT_U16_NE:#if WORDS_BIGENDIAN			stream_attrs.is_bigendian = TRUE;#else			stream_attrs.is_bigendian = FALSE;#endif			break;		case FMT_S16_LE:		case FMT_U16_LE:			stream_attrs.is_bigendian = FALSE;			break;		case FMT_U16_BE:		case FMT_S16_BE:			stream_attrs.is_bigendian = TRUE;			break;	}	/* Check the card's capabilities */	ctl_dev = g_strconcat(get_audiodev(), "ctl", NULL);	/* FIXME: Check if open fails */	audiofd = open(ctl_dev, O_RDONLY);	g_free(ctl_dev);	ioctl(audiofd, AUDIO_GETDEV, &aud_dev);	close(audiofd);    	if (!strcmp(aud_dev.name, "SUNW,CS4231"))	{		/* CS4231 card (SS[45], Ultra's) */		/* 16 bit sound only */		stream_attrs.output_precision=16;		stream_attrs.is_signed = TRUE;	}	else if (!strcmp(aud_dev.name, "SUNW,dbri"))	{		/* DBRI card (SS10's and 20's) */		/* 16 bit sound only           */		stream_attrs.output_precision=16;		stream_attrs.is_signed = TRUE;	}	else if (!strcmp(aud_dev.name, "SUNW,audioens"))	{		/* Ensoniq1371/1373 and Creative Labs 5880 audio controller */		stream_attrs.output_precision=stream_attrs.precision;		stream_attrs.is_signed = TRUE;		sun_cfg.channel_flags = 0;	}	else if (!strcmp(aud_dev.name, "SUNW,sb16") || !strcmp(aud_dev.name, "TOOLS,sbpci"))	{		/* Sound blaster (or compatible, inc AWE32/64) */		/* 8 or 16 bit sound */		/* Also SB PCI card using driver from http://www.tools.de/solaris/sbpci/ */		stream_attrs.output_precision = stream_attrs.precision;	}	else if (!strcmp(aud_dev.name, "SUNW,sbpro"))	{		/* Sound blaster pro (or compatible) */		/* 8 bit sound only, and only up to 22,050Hz in stereo */		/* Currently, the 22kHz limit is not worked around */		stream_attrs.output_precision = 8;	}	else if (!strcmp(aud_dev.name, "SUNW,audiots"))	{		/* AUDIOTS card (Sun Blade 100's) */		/* 16 bit sound only           */		stream_attrs.output_precision=16;		stream_attrs.is_signed = TRUE;	}	else if (!strcmp(aud_dev.name, "USB Audio"))	{		/* USB Audio (usb_ac) */		/* 8 or 16 bit sound */		stream_attrs.output_precision = stream_attrs.precision;	}	else	{		g_warning("solaris output: Unknown sound card type: %s", aud_dev.name);		g_warning("solaris output: Assuming capable of the bitstream");		stream_attrs.output_precision = stream_attrs.precision;	}		stream_attrs.bps = rate * nch;	if (stream_attrs.precision == 16)		stream_attrs.bps *= 2;	stream_attrs.channels = nch;	stream_attrs.sample_rate = rate;	/* Define the length for the buffer */	buffer_len = (sun_cfg.buffer_size * stream_attrs.bps) / 1000;	prebuffer_size = (buffer_len * sun_cfg.prebuffer) / 100;	if (buffer_len - prebuffer_size < 4096)		prebuffer_size = buffer_len - 4096;	buffer_ptr = g_malloc0(buffer_len);	buffer_write = buffer_ptr;	buffer_read = buffer_ptr;	buffer_end = buffer_ptr + buffer_len;	/* Open the audio device */	if (abuffer_startup())	{		/* Shutdown the buffer */		abuffer_shutdown();		return(0);	}	pthread_create(&buffer_thread, NULL, abuffer_loop, NULL);	while (audiofd == -2)		xmms_usleep(10000);	if (audiofd == -1)	{		pthread_join(buffer_thread, NULL);		return 0;	}	return 1;}/* This was in mixer.c for the OSS driver, but since we _have_ * to have the audio device open for writing, it has to be here. * The alternative is to have fd defined in Sun.h and used as * an extern, but that is messier and probably more trouble than * it's worth *//* * xmms expects 0<=volume<=100; Solaris audio is 0<=vol<=255 *//* * l is returned with the left channel volume, * r is returned with the right channel volume *//* get volume doesn't require write on audio device                    *//* However, if we have audio device open, might as well save an open() *//* This is called fairly regularly by XMMS (for visual volume slider,  *//* I assume) so is worth optimising.  As a result, this is now         *//* optimised for speed, not readability.                               */void abuffer_get_volume(int *left, int *right){	audio_info_t info;	/* Since we do not know if CD is playing or not, we need ctlfd 	   open all the time. */	if (ctlfd < 0)		init_ctlfd(); 		if (ctlfd == -1)		return;	if (ioctl (ctlfd, AUDIO_GETINFO, &info) >= 0)	{		/* Try to figure how to get values. */		int gain = ((info.play.gain - AUDIO_MIN_GAIN) * 100) / (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN);		int balance = ((info.play.balance - AUDIO_MID_BALANCE) * 100) /			(AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE);		if (balance == 0)		{			*left = gain;			*right = gain;		}		else if (balance > 0)		{			*right = gain;			*left = (gain * (100 - balance)) / 100;		}		else		{			*left = gain;			*right = (gain * (100 + balance)) / 100;		}	}}/* * Set volume (gain) */void abuffer_set_volume(int left, int right){	audio_info_t info;	/* Since we do not know if CD is playing or not, we need ctlfd 	   open all the time. */	if (ctlfd < 0)		init_ctlfd(); 		if (ctlfd == -1)		return;			AUDIO_INITINFO (&info);        /* Calculate gain and volume. */	info.play.gain = (MAX(left, right) * (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)) / 100;	if (left + right == 0)		info.play.balance = AUDIO_MID_BALANCE;	else		info.play.balance = AUDIO_LEFT_BALANCE + (right * AUDIO_RIGHT_BALANCE) / (left + right);        /* It seems that the sound card (at least CS4321 on Ultra10) truncates           the last three bits of the volume.  Round it so that it does not keep           drifting away.           Ideally, this should be somehow automatically determined. */	/* FIXME:  Read it back instead? */        if ((info.play.gain & 0xf) >= 4)		info.play.gain += 4;        info.record.gain =  info.play.gain;        info.record.balance = info.play.balance;        ioctl (ctlfd, AUDIO_SETINFO, &info);}/* * Simple function to check if audio device is open  * Returns 1 if open, 0 otherwise. */int abuffer_isopen(void){	if (audiofd < 0)		return 0;	return 1;}/* * abuffer_update_dev() * Function to update the open devices in case they have changed (eg, someone * has used audiocontrol.  This makes it a bit friendlier to other apps. * returns 0 on success, 1 on failure. */int abuffer_update_dev(void){	audio_info_t ainfo;	if (audiofd < 0)		return 1;	if (ioctl(audiofd, AUDIO_GETINFO, &ainfo) == -1)		return 1;    	sun_cfg.channel_flags = ainfo.play.port;	return 0;}/* * abuffer_set_dev() * Function to set the output devices * returns 0 on success, 1 if device not open */int abuffer_set_dev(void){	audio_info_t ainfo;	if (audiofd < 0)		return 1;	AUDIO_INITINFO(&ainfo);	ainfo.play.port = sun_cfg.channel_flags;	ioctl(audiofd, AUDIO_SETINFO, &ainfo);	return 0;}

⌨️ 快捷键说明

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