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

📄 audio.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
📖 第 1 页 / 共 2 页
字号:
	type *ptr = data;				\	for (i = 0; i < length; i += 2)			\	{						\		*ptr = *ptr * alsa_cfg.vol.left / 100;	\		ptr++;					\		*ptr = *ptr * alsa_cfg.vol.right / 100;	\		ptr++;					\	}						\} while (0)#define MONO_ADJUST8(type)			\do {						\	type *ptr = data;			\	for (i = 0; i < length; i += 4)		\	{					\		*ptr = *ptr * vol / 100;	\		ptr++;				\	}					\} while (0)#define VOLUME_ADJUST8(type)			\do {						\	if (channels == 2)			\		STEREO_ADJUST8(type);		\	else					\		MONO_ADJUST8(type);		\} while (0)	static void volume_adjust(void* data, int length, AFormat fmt, int channels){	int i, vol;	if ((alsa_cfg.vol.left == 100 && alsa_cfg.vol.right == 100) ||	    (channels == 1 &&	     (alsa_cfg.vol.left == 100 || alsa_cfg.vol.right == 100)))		return;	vol = MAX(alsa_cfg.vol.left, alsa_cfg.vol.right);		switch (fmt)	{		case FMT_S16_LE:			VOLUME_ADJUST(gint16, GINT16, LE);			break;		case FMT_U16_LE:			VOLUME_ADJUST(guint16, GUINT16, LE);			break;		case FMT_S16_BE:			VOLUME_ADJUST(gint16, GINT16, BE);			break;		case FMT_U16_BE:			VOLUME_ADJUST(guint16, GUINT16, BE);			break;		case FMT_S8:			VOLUME_ADJUST8(gint8);			break;		case FMT_U8:			VOLUME_ADJUST8(guint8);			break;		default:			g_warning("volue_adjust(): unhandled format: %d", fmt);			break;	}}void alsa_write(gpointer data, int length){	EffectPlugin *ep;	if (paused)		return;	force_start = FALSE;	if (effects_enabled() && (ep = get_current_effect_plugin()))	{		int new_freq = inputf->rate;		int new_chn = inputf->channels;		AFormat f = inputf->xmms_format;				if (ep->query_format)		{			ep->query_format(&f, &new_freq, &new_chn);						if (f != effectf->xmms_format ||			    new_freq != effectf->rate ||			    new_chn != effectf->channels)			{				debug("Changing audio format for effect plugin");				g_free(effectf);				effectf = snd_format_from_xmms(f, new_freq,							       new_chn);				alsa_reopen(effectf);			}					}			length = ep->mod_samples(&data, length,					 inputf->xmms_format,					 inputf->rate,					 inputf->channels);	}	else if (effectf)	{		g_free(effectf);		effectf = NULL;		effectf = snd_format_from_xmms(inputf->xmms_format,					       inputf->rate,					       inputf->channels);		alsa_reopen(inputf);	}	if (alsa_convert_func != NULL)		length = alsa_convert_func(convertb, &data, length);	if (alsa_stereo_convert_func != NULL)		length = alsa_stereo_convert_func(convertb, &data, length);	if (alsa_frequency_convert_func != NULL)		length = alsa_frequency_convert_func(convertb, &data, length,						     effectf->rate,						     outputf->rate);	if (alsa_cfg.soft_volume)		volume_adjust(data, length, outputf->xmms_format, outputf->channels);	if (mmap)		alsa_mmap_audio(data, length);	else		alsa_write_audio(data, length);}static void alsa_write_audio(gpointer data, int length){	snd_pcm_sframes_t written_frames;	while (length > 0)	{		int frames = snd_pcm_bytes_to_frames(alsa_pcm, length);		written_frames = snd_pcm_writei(alsa_pcm, data, frames);				if (written_frames > 0)		{			int written = snd_pcm_frames_to_bytes(alsa_pcm,							      written_frames);			alsa_total_written += written;			length -= written;			data = (char*) data + written;		}		else if (written_frames == -EPIPE)			xrun_recover();		else		{			g_warning("alsa_write_audio(): write error: %s",				  snd_strerror(-written_frames));			break;		}	}}static void alsa_mmap_audio(char *data, int length){	int cnt = 0, err;	snd_pcm_uframes_t offset, frames, frame;	const snd_pcm_channel_area_t *chan_areas = areas;	int channel_offset = 0, channel;	ssize_t sample_size, offset_bytes, step;	alsa_get_avail();	while (length > 0)	{		frames = snd_pcm_bytes_to_frames(alsa_pcm, length);		if ((err = snd_pcm_mmap_begin(alsa_pcm, &chan_areas, &offset, &frames) < 0))			g_warning("alsa_mmap_audio(): snd_pcm_mmap_begin() "				  "failed: %s", snd_strerror(-err));		cnt = snd_pcm_frames_to_bytes(alsa_pcm, frames);		sample_size = snd_pcm_samples_to_bytes(alsa_pcm, 1);		step = chan_areas[0].step / 8;		offset_bytes = offset * step;		for (frame = 0; frame < frames; frame++)		{			for (channel = 0; channel < outputf->channels; channel++)			{				char *ptr = chan_areas[channel].addr;				memcpy(ptr + chan_areas[channel].first / 8 +				       offset_bytes,				       data + channel_offset, sample_size);				channel_offset += sample_size;			}			offset_bytes += step;		}					err = snd_pcm_mmap_commit(alsa_pcm, offset, frames);		if (err == -EPIPE)			xrun_recover();		else if (err < 0)			g_warning("alsa_mmap_audio(): snd_pcm_mmap_commit() "				  "failed: %s", snd_strerror(-err));		else if (err != frames)			g_warning("alsa_mmap_audio(): snd_pcm_mmap_commit "				  "returned %d, expected %d", err, (int)frames);				alsa_total_written += cnt;				length -= cnt;	}}int alsa_open(AFormat fmt, int rate, int nch){	debug("Opening device");	inputf = snd_format_from_xmms(fmt, rate, nch);	effectf = snd_format_from_xmms(fmt, rate, nch);		if (alsa_cfg.debug)		snd_output_stdio_attach(&logs, stdout, 0);	mmap = alsa_cfg.mmap;	if (alsa_setup(inputf) < 0)	{		alsa_close();		return 0;	}	alsa_setup_mixer();	convertb = xmms_convert_buffers_new();		alsa_total_written = 0;	going = TRUE;	paused = FALSE;	force_start = FALSE;		snd_pcm_prepare(alsa_pcm);		return 1;}static struct snd_format * snd_format_from_xmms(AFormat fmt, int rate, int channels){	struct snd_format *f = g_malloc(sizeof(struct snd_format));	int i;	f->xmms_format = fmt;	f->format = SND_PCM_FORMAT_UNKNOWN;	for (i = 0; i < sizeof(format_table) / sizeof(format_table[0]); i++)		if (format_table[i].xmms == fmt)		{			f->format = format_table[i].alsa;			break;		}	/* Get rid of _NE */	for (i = 0; i < sizeof(format_table) / sizeof(format_table[0]); i++)		if (format_table[i].alsa == f->format)		{			f->xmms_format = format_table[i].xmms;			break;		}	f->rate = rate;	f->channels = channels;	return f;}static int format_from_alsa(snd_pcm_format_t fmt){	int i;	for (i = 0; i < sizeof(format_table) / sizeof(format_table[0]); i++)		if (format_table[i].alsa == fmt)			return format_table[i].xmms;	g_warning("Unsupported format: %s", snd_pcm_format_name(fmt));	return -1;}static int alsa_setup(struct snd_format *f){	int err;	snd_pcm_hw_params_t *hwparams;	snd_pcm_sw_params_t *swparams;	int alsa_buffer_time, bits_per_sample;	unsigned int alsa_period_time;	snd_pcm_uframes_t alsa_buffer_size, alsa_period_size;	debug("alsa_setup");	alsa_convert_func = NULL;	alsa_stereo_convert_func = NULL;	alsa_frequency_convert_func = NULL;	outputf = snd_format_from_xmms(effectf->xmms_format,				       effectf->rate,				       effectf->channels);	debug("Opening device: %s", alsa_cfg.pcm_device);	/* FIXME: Can snd_pcm_open() return EAGAIN? */	if ((err = snd_pcm_open(&alsa_pcm, alsa_cfg.pcm_device,				SND_PCM_STREAM_PLAYBACK,				SND_PCM_NONBLOCK)) < 0)	{		g_warning("alsa_setup(): Failed to open pcm device (%s): %s",			  alsa_cfg.pcm_device, snd_strerror(-err));		alsa_pcm = NULL;		return -1;	}	snd_pcm_nonblock(alsa_pcm, FALSE);	if (alsa_cfg.debug)	{		snd_pcm_info_t *info;		int alsa_card, alsa_device, alsa_subdevice;		snd_pcm_info_alloca(&info);		snd_pcm_info(alsa_pcm, info);		alsa_card =  snd_pcm_info_get_card(info);		alsa_device = snd_pcm_info_get_device(info);		alsa_subdevice = snd_pcm_info_get_subdevice(info);		printf("Card %i, Device %i, Subdevice %i\n",		       alsa_card, alsa_device, alsa_subdevice);	}	snd_pcm_hw_params_alloca(&hwparams);	if ((err = snd_pcm_hw_params_any(alsa_pcm, hwparams)) < 0)	{		g_warning("alsa_setup(): No configuration available for "			  "playback: %s", snd_strerror(-err));		return -1;	}	if (mmap &&	    (err = snd_pcm_hw_params_set_access(alsa_pcm, hwparams,						SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)	{		g_message("alsa_setup(): Cannot set mmap'ed mode: %s. "			  "falling back to direct write", snd_strerror(-err));		mmap = 0;	}	if (!mmap &&	    (err = snd_pcm_hw_params_set_access(alsa_pcm, hwparams,						SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)	{		g_warning("alsa_setup(): Cannot set direct write mode: %s",			  snd_strerror(-err));		return -1;	}	if ((err = snd_pcm_hw_params_set_format(alsa_pcm, hwparams, outputf->format)) < 0)	{		/*		 * Try if one of these format work (one of them should work		 * on almost all soundcards)		 */		snd_pcm_format_t formats[] = {SND_PCM_FORMAT_S16_LE,					      SND_PCM_FORMAT_S16_BE,					      SND_PCM_FORMAT_U8};		int i;		for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)		{			if (snd_pcm_hw_params_set_format(alsa_pcm, hwparams,							 formats[i]) == 0)			{				outputf->format = formats[i];				break;			}		}		if (outputf->format != effectf->format)		{			outputf->xmms_format =				format_from_alsa(outputf->format);			debug("Converting format from %d to %d",			      effectf->xmms_format, outputf->xmms_format);			if (outputf->xmms_format < 0)				return -1;			alsa_convert_func =				xmms_convert_get_func(outputf->xmms_format,						      effectf->xmms_format);			if (alsa_convert_func == NULL)				return -1;		}		else		{			g_warning("alsa_setup(): Sample format not "				  "available for playback: %s",				  snd_strerror(-err));			return -1;		}	}	snd_pcm_hw_params_set_channels_near(alsa_pcm, hwparams, &outputf->channels);	if (outputf->channels != effectf->channels)	{		debug("Converting channels from %d to %d",		      effectf->channels, outputf->channels);		alsa_stereo_convert_func =			xmms_convert_get_channel_func(outputf->xmms_format,						      outputf->channels,						      effectf->channels);		if (alsa_stereo_convert_func == NULL)			return -1;	}	snd_pcm_hw_params_set_rate_near(alsa_pcm, hwparams, &outputf->rate, 0);	if (outputf->rate == 0)	{		g_warning("alsa_setup(): No usable samplerate available.");		return -1;	}	if (outputf->rate != effectf->rate)	{		debug("Converting samplerate from %d to %d",		      effectf->rate, outputf->rate);		alsa_frequency_convert_func =			xmms_convert_get_frequency_func(outputf->xmms_format,							outputf->channels);		if (alsa_frequency_convert_func == NULL)			return -1;	}	alsa_buffer_time = alsa_cfg.buffer_time * 1000;	if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_pcm, hwparams,							  &alsa_buffer_time, 0)) < 0)	{		g_warning("alsa_setup(): Set buffer time failed: %s.",			  snd_strerror(-err));		return -1;	}	alsa_period_time = alsa_cfg.period_time * 1000;	if ((err = snd_pcm_hw_params_set_period_time_near(alsa_pcm, hwparams,							  &alsa_period_time, 0)) < 0)	{		g_warning("alsa_setup(): Set period time failed: %s.",			  snd_strerror(-err));		return -1;	}	if (snd_pcm_hw_params(alsa_pcm, hwparams) < 0)	{		if (alsa_cfg.debug)			snd_pcm_hw_params_dump(hwparams, logs);		g_warning("alsa_setup(): Unable to install hw params");		return -1;	}	if ((err = snd_pcm_hw_params_get_buffer_size(hwparams, &alsa_buffer_size)) < 0)	{		g_warning("alsa_setup(): snd_pcm_hw_params_get_buffer_size() "			  "failed: %s",			  snd_strerror(-err));		return -1;	}	if ((err = snd_pcm_hw_params_get_period_size(hwparams, &alsa_period_size, 0)) < 0)	{		g_warning("alsa_setup(): snd_pcm_hw_params_get_period_size() "			  "failed: %s",			  snd_strerror(-err));		return -1;	}	alsa_can_pause = snd_pcm_hw_params_can_pause(hwparams);	snd_pcm_sw_params_alloca(&swparams);	snd_pcm_sw_params_current(alsa_pcm, swparams);	/* This has effect for non-mmap only */	if ((err = snd_pcm_sw_params_set_start_threshold(alsa_pcm,			swparams, alsa_buffer_size - alsa_period_size) < 0))		g_warning("alsa_setup(): setting start "			  "threshold failed: %s", snd_strerror(-err));	if (snd_pcm_sw_params(alsa_pcm, swparams) < 0)	{		g_warning("alsa_setup(): Unable to install sw params");		return -1;	}	if (alsa_cfg.debug)	{		snd_pcm_sw_params_dump(swparams, logs);		snd_pcm_dump(alsa_pcm, logs);	}	bits_per_sample = snd_pcm_format_physical_width(outputf->format);	alsa_bps = (outputf->rate * bits_per_sample * outputf->channels) >> 3;	if (mmap)	{		int chn;		buffer = g_malloc(alsa_period_size * bits_per_sample / 8 * outputf->channels);		areas = g_malloc0(outputf->channels * sizeof(snd_pcm_channel_area_t));				for (chn = 0; chn < outputf->channels; chn++)		{			areas[chn].addr = buffer;			areas[chn].first = chn * bits_per_sample;			areas[chn].step = outputf->channels * bits_per_sample;		}	}	debug("Device setup: buffer time: %i, size: %i.", alsa_buffer_time,	      snd_pcm_frames_to_bytes(alsa_pcm, alsa_buffer_size));	debug("bits per sample: %i; frame size: %i; Bps: %i",	      bits_per_sample, snd_pcm_frames_to_bytes(alsa_pcm, 1), alsa_bps);	return 0;}

⌨️ 快捷键说明

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