sound/core/oss/mulaw.c

Source file repositories/reference/linux-study-clean/sound/core/oss/mulaw.c

File Facts

System
Linux kernel
Corpus path
sound/core/oss/mulaw.c
Extension
.c
Size
9829 bytes
Lines
333
Domain
Driver Families
Bucket
sound/core
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mulaw_priv {
	mulaw_f func;
	int cvt_endian;			/* need endian conversion? */
	unsigned int native_ofs;	/* byte offset in native format */
	unsigned int copy_ofs;		/* byte offset in s16 format */
	unsigned int native_bytes;	/* byte size of the native format */
	unsigned int copy_bytes;	/* bytes to copy per conversion */
	u16 flip; /* MSB flip for signedness, done after endian conversion */
};

static inline void cvt_s16_to_native(struct mulaw_priv *data,
				     unsigned char *dst, u16 sample)
{
	sample ^= data->flip;
	if (data->cvt_endian)
		sample = swab16(sample);
	if (data->native_bytes > data->copy_bytes)
		memset(dst, 0, data->native_bytes);
	memcpy(dst + data->native_ofs, (char *)&sample + data->copy_ofs,
	       data->copy_bytes);
}

static void mulaw_decode(struct snd_pcm_plugin *plugin,
			const struct snd_pcm_plugin_channel *src_channels,
			struct snd_pcm_plugin_channel *dst_channels,
			snd_pcm_uframes_t frames)
{
	struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
	int channel;
	int nchannels = plugin->src_format.channels;
	for (channel = 0; channel < nchannels; ++channel) {
		char *src;
		char *dst;
		int src_step, dst_step;
		snd_pcm_uframes_t frames1;
		if (!src_channels[channel].enabled) {
			if (dst_channels[channel].wanted)
				snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format);
			dst_channels[channel].enabled = 0;
			continue;
		}
		dst_channels[channel].enabled = 1;
		src = src_channels[channel].area.addr + src_channels[channel].area.first / 8;
		dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;
		src_step = src_channels[channel].area.step / 8;
		dst_step = dst_channels[channel].area.step / 8;
		frames1 = frames;
		while (frames1-- > 0) {
			signed short sample = ulaw2linear(*src);
			cvt_s16_to_native(data, dst, sample);
			src += src_step;
			dst += dst_step;
		}
	}
}

static inline signed short cvt_native_to_s16(struct mulaw_priv *data,
					     unsigned char *src)
{
	u16 sample = 0;
	memcpy((char *)&sample + data->copy_ofs, src + data->native_ofs,
	       data->copy_bytes);
	if (data->cvt_endian)
		sample = swab16(sample);
	sample ^= data->flip;
	return (signed short)sample;
}

static void mulaw_encode(struct snd_pcm_plugin *plugin,
			const struct snd_pcm_plugin_channel *src_channels,
			struct snd_pcm_plugin_channel *dst_channels,
			snd_pcm_uframes_t frames)
{
	struct mulaw_priv *data = (struct mulaw_priv *)plugin->extra_data;
	int channel;
	int nchannels = plugin->src_format.channels;
	for (channel = 0; channel < nchannels; ++channel) {
		char *src;
		char *dst;
		int src_step, dst_step;
		snd_pcm_uframes_t frames1;
		if (!src_channels[channel].enabled) {
			if (dst_channels[channel].wanted)
				snd_pcm_area_silence(&dst_channels[channel].area, 0, frames, plugin->dst_format.format);
			dst_channels[channel].enabled = 0;
			continue;
		}
		dst_channels[channel].enabled = 1;
		src = src_channels[channel].area.addr + src_channels[channel].area.first / 8;
		dst = dst_channels[channel].area.addr + dst_channels[channel].area.first / 8;

Annotation

Implementation Notes