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

📄 audio.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  XMMS - Cross-platform multimedia player *  Copyright (C) 1998-2001  Peter Alm, Mikael Alm, Olle Hallnas, *                           Thomas Nilsson and 4Front Technologies *  Copyright (C) 1999-2001  Haavard Kvaalen * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "OSS.h"#include "libxmms/util.h"#include <errno.h>#define NFRAGS		32static gint fd = 0;static char *buffer;static gboolean going, prebuffer, paused, unpause, do_pause, remove_prebuffer;static gint device_buffer_used, buffer_size, prebuffer_size, blk_size;static gint rd_index = 0, wr_index = 0;static gint output_time_offset = 0;static guint64 written = 0, output_bytes = 0;static gint flush;static gint fragsize, device_buffer_size;static gchar *device_name;static pthread_t buffer_thread;static gboolean realtime, select_works;static int (*oss_convert_func)(void **data, int length);static int (*oss_stereo_convert_func)(void **data, int length, int fmt);struct format_info {	union {		AFormat xmms;		int oss;	} format;	int frequency;	int channels;	int bps;};/* * The format of the data from the input plugin * This will never change during a song.  */struct format_info input;/* * The format we get from the effect plugin. * This will be different from input if the effect plugin does * some kind of format conversion. */struct format_info effect;/* * The format of the data we actually send to the soundcard. * This might be different from effect if we need to resample or do * some other format conversion. */struct format_info output;static void oss_calc_device_buffer_used(void){	audio_buf_info buf_info;	if(paused)		device_buffer_used = 0;	else if (!ioctl(fd, SNDCTL_DSP_GETOSPACE, &buf_info))		device_buffer_used = (buf_info.fragstotal * buf_info.fragsize) - buf_info.bytes;}static gint oss_downsample(gpointer ob, guint length, guint speed, guint espeed);static int oss_calc_bitrate(int oss_fmt, int rate, int channels){	int bitrate = rate * channels;	if (oss_fmt == AFMT_U16_BE || oss_fmt == AFMT_U16_LE ||	    oss_fmt == AFMT_S16_BE || oss_fmt == AFMT_S16_LE)		bitrate *= 2;	return bitrate;}static int oss_get_format(AFormat fmt){	int format = 0;	switch (fmt)	{		case FMT_U8:			format = AFMT_U8;			break;		case FMT_S8:			format = AFMT_S8;			break;		case FMT_U16_LE:			format = AFMT_U16_LE;			break;		case FMT_U16_BE:			format = AFMT_U16_BE;			break;		case FMT_U16_NE:#ifdef WORDS_BIGENDIAN			format = AFMT_U16_BE;#else			format = AFMT_U16_LE;#endif			break;		case FMT_S16_LE:			format = AFMT_S16_LE;			break;		case FMT_S16_BE:			format = AFMT_S16_BE;			break;		case FMT_S16_NE:#ifdef WORDS_BIGENDIAN			format = AFMT_S16_BE;#else			format = AFMT_S16_LE;#endif			break;	}	return format;}static void oss_setup_format(AFormat fmt, int rate, int nch){	effect.format.xmms = fmt;	effect.frequency = rate;	effect.channels = nch;	effect.bps = oss_calc_bitrate(oss_get_format(fmt), rate, nch);	output.format.oss = oss_get_format(fmt);	output.frequency = rate;	output.channels = nch;	fragsize = 0;	while ((1L << fragsize) < effect.bps / 25)		fragsize++;	fragsize--;	device_buffer_size = ((1L << fragsize) * (NFRAGS + 1));	oss_set_audio_params();	output.bps = oss_calc_bitrate(output.format.oss, output.frequency,				      output.channels);}	gint oss_get_written_time(void){	if (!going)		return 0;	return (written * 1000) / effect.bps;}gint oss_get_output_time(void){	guint64 bytes;	if (!fd || !going)		return 0;	if (realtime)		oss_calc_device_buffer_used();	bytes = output_bytes < device_buffer_used ?		0 : output_bytes - device_buffer_used;	return output_time_offset + ((bytes * 1000) / output.bps);}static int oss_used(void){	if (realtime)		return 0;	else	{		if (wr_index >= rd_index)			return wr_index - rd_index;		return buffer_size - (rd_index - wr_index);	}}gint oss_playing(void){	if(!going)		return 0;	if(realtime)		oss_calc_device_buffer_used();	if (!oss_used() && (device_buffer_used - (3 * blk_size)) <= 0)		return FALSE;	return TRUE;}gint oss_free(void){	if (!realtime)	{		if (remove_prebuffer && prebuffer)		{			prebuffer = FALSE;			remove_prebuffer = FALSE;		}		if (prebuffer)			remove_prebuffer = TRUE;		if (rd_index > wr_index)			return (rd_index - wr_index) - device_buffer_size - 1;		return (buffer_size - (wr_index - rd_index)) - device_buffer_size - 1;	}	else		if (paused)			return 0;		else			return 1000000;}static inline ssize_t write_all(int fd, const void *buf, size_t count){	ssize_t done = 0;	do {		ssize_t n = write(fd, buf, count - done);		if (n == -1)		{			if (errno == EINTR)				continue;			else				break;		}		done += n;	} while (count > done);	return done;}static void oss_write_audio(gpointer data, int length){	audio_buf_info abuf_info;	AFormat new_format;	int new_frequency, new_channels;	EffectPlugin *ep;		new_format = input.format.xmms;	new_frequency = input.frequency;	new_channels = input.channels;		ep = get_current_effect_plugin();	if(effects_enabled() && ep && ep->query_format)	{		ep->query_format(&new_format,&new_frequency,&new_channels);	}		if (new_format != effect.format.xmms ||	    new_frequency != effect.frequency ||	    new_channels != effect.channels)	{		output_time_offset += (output_bytes * 1000) / output.bps;		output_bytes = 0;		close(fd);		fd = open(device_name,O_WRONLY);		oss_setup_format(new_format, new_frequency, new_channels);	}	if (effects_enabled() && ep && ep->mod_samples)		length = ep->mod_samples(&data, length,					 input.format.xmms,					 input.frequency,					 input.channels);	if (realtime && !ioctl(fd, SNDCTL_DSP_GETOSPACE, &abuf_info))	{		while (abuf_info.bytes < length)		{			xmms_usleep(10000);			if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &abuf_info))				break;		}	}	if (oss_convert_func != NULL)		length = oss_convert_func(&data, length);	if (oss_stereo_convert_func != NULL)		length = oss_stereo_convert_func(&data, length,						 output.format.oss);	if (effect.frequency == output.frequency)		output_bytes += write_all(fd, data, length);	else		output_bytes += oss_downsample(data, length,					       effect.frequency,					       output.frequency);}static void swap_endian(guint16 *data, int length){	int i;	for (i = 0; i < length; i += 2, data++)		*data = GUINT16_SWAP_LE_BE(*data);}#define NOT_NATIVE_ENDIAN ((IS_BIG_ENDIAN &&				\			   (output.format.oss == AFMT_S16_LE ||		\			    output.format.oss == AFMT_U16_LE)) ||	\			  (!IS_BIG_ENDIAN &&				\			   (output.format.oss == AFMT_S16_BE ||		\			    output.format.oss == AFMT_U16_BE)))#define RESAMPLE_STEREO(sample_type)				\do {								\	const gint shift = sizeof (sample_type);		\        gint i, in_samples, out_samples, x, delta;		\	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 = (in_samples << 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] *		\			  ((1<<12) - frac) +			\			  inptr[((x1 >> 12) + 1) << 1] *	\			  frac) >> 12);				\

⌨️ 快捷键说明

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