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

📄 pcm_plugin.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			snd_pcm_plugin_free(plugin);			return err;		}      					    		err = snd_pcm_plugin_append(plugin);		if (err < 0) {			snd_pcm_plugin_free(plugin);			return err;		}		srcformat = tmpformat;		src_access = dst_access;	}	/* format change */	if (srcformat.format != dstformat.format) {		tmpformat.format = dstformat.format;		if (tmpformat.format == SNDRV_PCM_FORMAT_MU_LAW) {			err = snd_pcm_plugin_build_mulaw(plug,							 &srcformat, &tmpformat,							 &plugin);		}		else if (snd_pcm_format_linear(srcformat.format) &&			 snd_pcm_format_linear(tmpformat.format)) {			err = snd_pcm_plugin_build_linear(plug,							  &srcformat, &tmpformat,							  &plugin);		}		else			return -EINVAL;		pdprintf("format change: src=%i, dst=%i returns %i\n", srcformat.format, tmpformat.format, err);		if (err < 0)			return err;		err = snd_pcm_plugin_append(plugin);		if (err < 0) {			snd_pcm_plugin_free(plugin);			return err;		}		srcformat = tmpformat;		src_access = dst_access;	}	/* de-interleave */	if (src_access != dst_access) {		err = snd_pcm_plugin_build_copy(plug,						&srcformat,						&tmpformat,						&plugin);		pdprintf("interleave change (copy: returns %i)\n", err);		if (err < 0)			return err;		err = snd_pcm_plugin_append(plugin);		if (err < 0) {			snd_pcm_plugin_free(plugin);			return err;		}	}	return 0;}snd_pcm_sframes_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug,					 char *buf,					 snd_pcm_uframes_t count,					 snd_pcm_plugin_channel_t **channels){	snd_pcm_plugin_t *plugin;	snd_pcm_plugin_channel_t *v;	snd_pcm_plugin_format_t *format;	int width, nchannels, channel;	int stream = snd_pcm_plug_stream(plug);	snd_assert(buf != NULL, return -ENXIO);	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {		plugin = snd_pcm_plug_first(plug);		format = &plugin->src_format;	} else {		plugin = snd_pcm_plug_last(plug);		format = &plugin->dst_format;	}	v = plugin->buf_channels;	*channels = v;	if ((width = snd_pcm_format_physical_width(format->format)) < 0)		return width;	nchannels = format->channels;	snd_assert(plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || format->channels <= 1, return -ENXIO);	for (channel = 0; channel < nchannels; channel++, v++) {		v->enabled = 1;		v->wanted = (stream == SNDRV_PCM_STREAM_CAPTURE);		v->area.addr = buf;		v->area.first = channel * width;		v->area.step = nchannels * width;	}	return count;}int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,					bitset_t *client_vmask){	snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);	if (plugin == NULL) {		return 0;	} else {		int schannels = plugin->dst_format.channels;		bitset_t bs[bitset_size(schannels)];		bitset_t *srcmask;		bitset_t *dstmask = bs;		int err;		bitset_one(dstmask, schannels);		if (plugin == NULL) {			bitset_and(client_vmask, dstmask, schannels);			return 0;		}		while (1) {			err = plugin->src_channels_mask(plugin, dstmask, &srcmask);			if (err < 0)				return err;			dstmask = srcmask;			if (plugin->prev == NULL)				break;			plugin = plugin->prev;		}		bitset_and(client_vmask, dstmask, plugin->src_format.channels);		return 0;	}}int snd_pcm_plug_capture_channels_mask(snd_pcm_plug_t *plug,				       bitset_t *client_vmask){	snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);	if (plugin == NULL) {		return 0;	} else {		int schannels = plugin->src_format.channels;		bitset_t bs[bitset_size(schannels)];		bitset_t *srcmask = bs;		bitset_t *dstmask;		int err;		bitset_one(srcmask, schannels);		while (1) {			err = plugin->dst_channels_mask(plugin, srcmask, &dstmask);			if (err < 0)				return err;			srcmask = dstmask;			if (plugin->next == NULL)				break;			plugin = plugin->next;		}		bitset_and(client_vmask, srcmask, plugin->dst_format.channels);		return 0;	}}static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plug_t *plug,							  snd_pcm_plugin_channel_t *src_channels){	snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);	unsigned int nchannels = plugin->src_format.channels;	bitset_t bs[bitset_size(nchannels)];	bitset_t *srcmask = bs;	int err;	unsigned int channel;	for (channel = 0; channel < nchannels; channel++) {		if (src_channels[channel].enabled)			bitset_set(srcmask, channel);		else			bitset_reset(srcmask, channel);	}	err = snd_pcm_plug_playback_channels_mask(plug, srcmask);	if (err < 0)		return err;	for (channel = 0; channel < nchannels; channel++) {		if (!bitset_get(srcmask, channel))			src_channels[channel].enabled = 0;	}	return 0;}static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plug_t *plug,							 snd_pcm_plugin_channel_t *src_channels,							 snd_pcm_plugin_channel_t *client_channels){	snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);	unsigned int nchannels = plugin->dst_format.channels;	bitset_t bs[bitset_size(nchannels)];	bitset_t *dstmask = bs;	bitset_t *srcmask;	int err;	unsigned int channel;	for (channel = 0; channel < nchannels; channel++) {		if (client_channels[channel].enabled)			bitset_set(dstmask, channel);		else			bitset_reset(dstmask, channel);	}	while (plugin) {		err = plugin->src_channels_mask(plugin, dstmask, &srcmask);		if (err < 0)			return err;		dstmask = srcmask;		plugin = plugin->prev;	}	plugin = snd_pcm_plug_first(plug);	nchannels = plugin->src_format.channels;	for (channel = 0; channel < nchannels; channel++) {		if (!bitset_get(dstmask, channel))			src_channels[channel].enabled = 0;	}	return 0;}snd_pcm_sframes_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, snd_pcm_uframes_t size){	snd_pcm_plugin_t *plugin, *next;	snd_pcm_plugin_channel_t *dst_channels;	int err;	snd_pcm_sframes_t frames = size;	if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0)		return err;		plugin = snd_pcm_plug_first(plug);	while (plugin && frames > 0) {		if ((next = plugin->next) != NULL) {			snd_pcm_sframes_t frames1 = frames;			if (plugin->dst_frames)				frames1 = plugin->dst_frames(plugin, frames);			if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) {				return err;			}			if (err != frames1) {				frames = err;				if (plugin->src_frames)					frames = plugin->src_frames(plugin, frames1);			}		} else			dst_channels = 0;		pdprintf("write plugin: %s, %li\n", plugin->name, frames);		if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)			return frames;		src_channels = dst_channels;		plugin = next;	}	return snd_pcm_plug_client_size(plug, frames);}snd_pcm_sframes_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *dst_channels_final, snd_pcm_uframes_t size){	snd_pcm_plugin_t *plugin, *next;	snd_pcm_plugin_channel_t *src_channels, *dst_channels;	snd_pcm_sframes_t frames = size;	int err;	frames = snd_pcm_plug_slave_size(plug, frames);	if (frames < 0)		return frames;	src_channels = 0;	plugin = snd_pcm_plug_first(plug);	while (plugin && frames > 0) {		if ((next = plugin->next) != NULL) {			if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) {				return err;			}			frames = err;			if (!plugin->prev) {				if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final) < 0))					return err;			}		} else {			dst_channels = dst_channels_final;		}		pdprintf("read plugin: %s, %li\n", plugin->name, frames);		if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0)			return frames;		plugin = next;		src_channels = dst_channels;	}	return frames;}int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offset,			 size_t samples, int format){	/* FIXME: sub byte resolution and odd dst_offset */	char *dst;	unsigned int dst_step;	int width;	u_int64_t silence;	if (!dst_area->addr)		return 0;	dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;	width = snd_pcm_format_physical_width(format);	silence = snd_pcm_format_silence_64(format);	if (dst_area->step == (unsigned int) width) {		size_t dwords = samples * width / 64;		samples -= dwords * 64 / width;		while (dwords-- > 0)			*((u_int64_t*)dst)++ = silence;		if (samples == 0)			return 0;	}	dst_step = dst_area->step / 8;	switch (width) {	case 4: {		u_int8_t s0 = silence & 0xf0;		u_int8_t s1 = silence & 0x0f;		int dstbit = dst_area->first % 8;		int dstbit_step = dst_area->step % 8;		while (samples-- > 0) {			if (dstbit) {				*dst &= 0xf0;				*dst |= s1;			} else {				*dst &= 0x0f;				*dst |= s0;			}			dst += dst_step;			dstbit += dstbit_step;			if (dstbit == 8) {				dst++;				dstbit = 0;			}		}		break;	}	case 8: {		u_int8_t sil = silence;		while (samples-- > 0) {			*dst = sil;			dst += dst_step;		}		break;	}	case 16: {		u_int16_t sil = silence;		while (samples-- > 0) {			*(u_int16_t*)dst = sil;			dst += dst_step;		}		break;	}	case 32: {		u_int32_t sil = silence;		while (samples-- > 0) {			*(u_int32_t*)dst = sil;			dst += dst_step;		}		break;	}	case 64: {		while (samples-- > 0) {			*(u_int64_t*)dst = silence;			dst += dst_step;		}		break;	}	default:		snd_BUG();	}	return 0;}int snd_pcm_areas_silence(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,			  unsigned int channels, snd_pcm_uframes_t frames, int format){	int width = snd_pcm_format_physical_width(format);	while (channels > 0) {		void *addr = dst_areas->addr;		unsigned int step = dst_areas->step;		const snd_pcm_channel_area_t *begin = dst_areas;		int vc = channels;		unsigned int v = 0;		int err;		while (1) {			vc--;			v++;			dst_areas++;			if (vc == 0 ||			    dst_areas->addr != addr ||			    dst_areas->step != step ||			    dst_areas->first != dst_areas[-1].first + width)				break;		}		if (v > 1 && v * width == step) {			/* Collapse the areas */			snd_pcm_channel_area_t d;			d.addr = begin->addr;			d.first = begin->first;			d.step = width;			err = snd_pcm_area_silence(&d, dst_offset * v, frames * v, format);			channels -= v;		} else {			err = snd_pcm_area_silence(begin, dst_offset, frames, format);			dst_areas = begin + 1;			channels--;		}		if (err < 0)			return err;	}	return 0;}int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset,		      const snd_pcm_channel_area_t *dst_area, size_t dst_offset,		      size_t samples, int format){	/* FIXME: sub byte resolution and odd dst_offset */	char *src, *dst;	int width;	int src_step, dst_step;	src = src_area->addr + (src_area->first + src_area->step * src_offset) / 8;	if (!src_area->addr)		return snd_pcm_area_silence(dst_area, dst_offset, samples, format);	dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;	if (!dst_area->addr)		return 0;	width = snd_pcm_format_physical_width(format);	if (src_area->step == (unsigned int) width &&	    dst_area->step == (unsigned int) width) {		size_t bytes = samples * width / 8;		samples -= bytes * 8 / width;		memcpy(dst, src, bytes);		if (samples == 0)			return 0;	}	src_step = src_area->step / 8;	dst_step = dst_area->step / 8;	switch (width) {	case 4: {		int srcbit = src_area->first % 8;		int srcbit_step = src_area->step % 8;		int dstbit = dst_area->first % 8;		int dstbit_step = dst_area->step % 8;		while (samples-- > 0) {			unsigned char srcval;			if (srcbit)				srcval = *src & 0x0f;			else				srcval = *src & 0xf0;			if (dstbit)				*dst &= 0xf0;			else				*dst &= 0x0f;			*dst |= srcval;			src += src_step;			srcbit += srcbit_step;			if (srcbit == 8) {				src++;				srcbit = 0;			}			dst += dst_step;			dstbit += dstbit_step;			if (dstbit == 8) {				dst++;				dstbit = 0;			}		}		break;	}	case 8: {		while (samples-- > 0) {			*dst = *src;			src += src_step;			dst += dst_step;		}		break;	}	case 16: {		while (samples-- > 0) {			*(u_int16_t*)dst = *(u_int16_t*)src;			src += src_step;			dst += dst_step;		}		break;	}	case 32: {		while (samples-- > 0) {			*(u_int32_t*)dst = *(u_int32_t*)src;			src += src_step;			dst += dst_step;		}		break;	}	case 64: {		while (samples-- > 0) {			*(u_int64_t*)dst = *(u_int64_t*)src;			src += src_step;			dst += dst_step;		}		break;	}	default:		snd_BUG();	}	return 0;}int snd_pcm_areas_copy(const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset,		       const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset,		       unsigned int channels, snd_pcm_uframes_t frames, int format){	int width = snd_pcm_format_physical_width(format);	while (channels > 0) {		unsigned int step = src_areas->step;		void *src_addr = src_areas->addr;		const snd_pcm_channel_area_t *src_start = src_areas;		void *dst_addr = dst_areas->addr;		const snd_pcm_channel_area_t *dst_start = dst_areas;		int vc = channels;		unsigned int v = 0;		while (dst_areas->step == step) {			vc--;			v++;			src_areas++;			dst_areas++;			if (vc == 0 ||			    src_areas->step != step ||			    src_areas->addr != src_addr ||			    dst_areas->addr != dst_addr ||			    src_areas->first != src_areas[-1].first + width ||			    dst_areas->first != dst_areas[-1].first + width)				break;		}		if (v > 1 && v * width == step) {			/* Collapse the areas */			snd_pcm_channel_area_t s, d;			s.addr = src_start->addr;			s.first = src_start->first;			s.step = width;			d.addr = dst_start->addr;			d.first = dst_start->first;			d.step = width;			snd_pcm_area_copy(&s, src_offset * v, &d, dst_offset * v, frames * v, format);			channels -= v;		} else {			snd_pcm_area_copy(src_start, src_offset, dst_start, dst_offset, frames, format);			src_areas = src_start + 1;			dst_areas = dst_start + 1;			channels--;		}	}	return 0;}

⌨️ 快捷键说明

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