sound/core/oss/rate.c

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

File Facts

System
Linux kernel
Corpus path
sound/core/oss/rate.c
Extension
.c
Size
9159 bytes
Lines
334
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 rate_channel {
	signed short last_S1;
	signed short last_S2;
};
 
typedef void (*rate_f)(struct snd_pcm_plugin *plugin,
		       const struct snd_pcm_plugin_channel *src_channels,
		       struct snd_pcm_plugin_channel *dst_channels,
		       int src_frames, int dst_frames);

struct rate_priv {
	unsigned int pitch;
	unsigned int pos;
	rate_f func;
	snd_pcm_sframes_t old_src_frames, old_dst_frames;
	struct rate_channel channels[];
};

static void rate_init(struct snd_pcm_plugin *plugin)
{
	unsigned int channel;
	struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
	data->pos = 0;
	for (channel = 0; channel < plugin->src_format.channels; channel++) {
		data->channels[channel].last_S1 = 0;
		data->channels[channel].last_S2 = 0;
	}
}

static void resample_expand(struct snd_pcm_plugin *plugin,
			    const struct snd_pcm_plugin_channel *src_channels,
			    struct snd_pcm_plugin_channel *dst_channels,
			    int src_frames, int dst_frames)
{
	unsigned int pos = 0;
	signed int val;
	signed short S1, S2;
	signed short *src, *dst;
	unsigned int channel;
	int src_step, dst_step;
	int src_frames1, dst_frames1;
	struct rate_priv *data = (struct rate_priv *)plugin->extra_data;
	struct rate_channel *rchannels = data->channels;
	
	for (channel = 0; channel < plugin->src_format.channels; channel++) {
		pos = data->pos;
		S1 = rchannels->last_S1;
		S2 = rchannels->last_S2;
		if (!src_channels[channel].enabled) {
			if (dst_channels[channel].wanted)
				snd_pcm_area_silence(&dst_channels[channel].area, 0, dst_frames, plugin->dst_format.format);
			dst_channels[channel].enabled = 0;
			continue;
		}
		dst_channels[channel].enabled = 1;
		src = (signed short *)src_channels[channel].area.addr +
			src_channels[channel].area.first / 8 / 2;
		dst = (signed short *)dst_channels[channel].area.addr +
			dst_channels[channel].area.first / 8 / 2;
		src_step = src_channels[channel].area.step / 8 / 2;
		dst_step = dst_channels[channel].area.step / 8 / 2;
		src_frames1 = src_frames;
		dst_frames1 = dst_frames;
		while (dst_frames1-- > 0) {
			if (pos & ~R_MASK) {
				pos &= R_MASK;
				S1 = S2;
				if (src_frames1-- > 0) {
					S2 = *src;
					src += src_step;
				}
			}
			val = S1 + ((S2 - S1) * (signed int)pos) / BITS;
			if (val < -32768)
				val = -32768;
			else if (val > 32767)
				val = 32767;
			*dst = val;
			dst += dst_step;
			pos += data->pitch;
		}
		rchannels->last_S1 = S1;
		rchannels->last_S2 = S2;
		rchannels++;
	}
	data->pos = pos;
}

static void resample_shrink(struct snd_pcm_plugin *plugin,
			    const struct snd_pcm_plugin_channel *src_channels,

Annotation

Implementation Notes