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

📄 pcm_plugin.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	case SNDRV_PCM_STREAM_CAPTURE:		dstformat.format = params_format(params);		dstformat.rate = params_rate(params);		dstformat.channels = params_channels(params);		srcformat.format = params_format(slave_params);		srcformat.rate = params_rate(slave_params);		srcformat.channels = params_channels(slave_params);		src_access = (slave_interleaved ? SNDRV_PCM_ACCESS_RW_INTERLEAVED :						  SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);		dst_access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;		break;	default:		snd_BUG();		return -EINVAL;	}	tmpformat = srcformat;			pdprintf("srcformat: format=%i, rate=%i, channels=%i\n", 		 srcformat.format,		 srcformat.rate,		 srcformat.channels);	pdprintf("dstformat: format=%i, rate=%i, channels=%i\n", 		 dstformat.format,		 dstformat.rate,		 dstformat.channels);	/* Format change (linearization) */	if (! rate_match(srcformat.rate, dstformat.rate) &&	    ! snd_pcm_format_linear(srcformat.format)) {		if (srcformat.format != SNDRV_PCM_FORMAT_MU_LAW)			return -EINVAL;		tmpformat.format = SNDRV_PCM_FORMAT_S16;		err = snd_pcm_plugin_build_mulaw(plug,						 &srcformat, &tmpformat,						 &plugin);		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;	}	/* channels reduction */	if (srcformat.channels > dstformat.channels) {		tmpformat.channels = dstformat.channels;		err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);		pdprintf("channels reduction: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, 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;	}	/* rate resampling */	if (!rate_match(srcformat.rate, dstformat.rate)) {		if (srcformat.format != SNDRV_PCM_FORMAT_S16) {			/* convert to S16 for resampling */			tmpformat.format = SNDRV_PCM_FORMAT_S16;			err = snd_pcm_plugin_build_linear(plug,							  &srcformat, &tmpformat,							  &plugin);			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;		}		tmpformat.rate = dstformat.rate;        	err = snd_pcm_plugin_build_rate(plug,        					&srcformat, &tmpformat,						&plugin);		pdprintf("rate down resampling: src=%i, dst=%i returns %i\n", srcformat.rate, tmpformat.rate, 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;        }	/* format change */	if (srcformat.format != dstformat.format) {		tmpformat.format = dstformat.format;		if (srcformat.format == SNDRV_PCM_FORMAT_MU_LAW ||		    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;	}	/* channels extension */	if (srcformat.channels < dstformat.channels) {		tmpformat.channels = dstformat.channels;		err = snd_pcm_plugin_build_route(plug, &srcformat, &tmpformat, &plugin);		pdprintf("channels extension: src=%i, dst=%i returns %i\n", srcformat.channels, tmpformat.channels, 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(struct snd_pcm_substream *plug,					 char *buf,					 snd_pcm_uframes_t count,					 struct snd_pcm_plugin_channel **channels){	struct snd_pcm_plugin *plugin;	struct snd_pcm_plugin_channel *v;	struct snd_pcm_plugin_format *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->frames = count;		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;}snd_pcm_sframes_t snd_pcm_plug_write_transfer(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *src_channels, snd_pcm_uframes_t size){	struct snd_pcm_plugin *plugin, *next;	struct snd_pcm_plugin_channel *dst_channels;	int err;	snd_pcm_sframes_t frames = size;	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 = NULL;		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(struct snd_pcm_substream *plug, struct snd_pcm_plugin_channel *dst_channels_final, snd_pcm_uframes_t size){	struct snd_pcm_plugin *plugin, *next;	struct snd_pcm_plugin_channel *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 = NULL;	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;		} 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 struct snd_pcm_channel_area *dst_area, size_t dst_offset,			 size_t samples, int format){	/* FIXME: sub byte resolution and odd dst_offset */	unsigned char *dst;	unsigned int dst_step;	int width;	const unsigned char *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);	if (width <= 0)		return -EINVAL;	if (dst_area->step == (unsigned int) width && width >= 8)		return snd_pcm_format_set_silence(format, dst, samples);	silence = snd_pcm_format_silence_64(format);	if (! silence)		return -EINVAL;	dst_step = dst_area->step / 8;	if (width == 4) {		/* Ima ADPCM */		int dstbit = dst_area->first % 8;		int dstbit_step = dst_area->step % 8;		while (samples-- > 0) {			if (dstbit)				*dst &= 0xf0;			else				*dst &= 0x0f;			dst += dst_step;			dstbit += dstbit_step;			if (dstbit == 8) {				dst++;				dstbit = 0;			}		}	} else {		width /= 8;		while (samples-- > 0) {			memcpy(dst, silence, width);			dst += dst_step;		}	}	return 0;}int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,		      const struct snd_pcm_channel_area *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 (width <= 0)		return -EINVAL;	if (src_area->step == (unsigned int) width &&	    dst_area->step == (unsigned int) width && width >= 8) {		size_t bytes = samples * width / 8;		memcpy(dst, src, bytes);		return 0;	}	src_step = src_area->step / 8;	dst_step = dst_area->step / 8;	if (width == 4) {		/* Ima ADPCM */		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) >> 4;			if (dstbit)				*dst = (*dst & 0xf0) | srcval;			else				*dst = (*dst & 0x0f) | (srcval << 4);			src += src_step;			srcbit += srcbit_step;			if (srcbit == 8) {				src++;				srcbit = 0;			}			dst += dst_step;			dstbit += dstbit_step;			if (dstbit == 8) {				dst++;				dstbit = 0;			}		}	} else {		width /= 8;		while (samples-- > 0) {			memcpy(dst, src, width);			src += src_step;			dst += dst_step;		}	}	return 0;}#endif

⌨️ 快捷键说明

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