Blame axfer/frame-cache.c

Packit Service a9274b
// SPDX-License-Identifier: GPL-2.0
Packit Service a9274b
//
Packit Service a9274b
// frame-cache.c - maintainer of cache for data frame.
Packit Service a9274b
//
Packit Service a9274b
// Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
Packit Service a9274b
//
Packit Service a9274b
// Licensed under the terms of the GNU General Public License, version 2.
Packit Service a9274b
Packit Service a9274b
#include "frame-cache.h"
Packit Service a9274b
Packit Service a9274b
static void align_frames_in_i(struct frame_cache *cache,
Packit Service a9274b
			      unsigned int consumed_count)
Packit Service a9274b
{
Packit Service a9274b
	char *buf = cache->buf;
Packit Service a9274b
	unsigned int offset;
Packit Service a9274b
	unsigned int size;
Packit Service a9274b
Packit Service a9274b
	cache->remained_count -= consumed_count;
Packit Service a9274b
Packit Service a9274b
	offset = cache->bytes_per_sample * cache->samples_per_frame *
Packit Service a9274b
		 consumed_count;
Packit Service a9274b
	size = cache->bytes_per_sample * cache->samples_per_frame *
Packit Service a9274b
	       cache->remained_count;
Packit Service a9274b
	memmove(buf, buf + offset, size);
Packit Service a9274b
Packit Service a9274b
	cache->buf_ptr = buf + size;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void align_frames_in_n(struct frame_cache *cache,
Packit Service a9274b
			      unsigned int consumed_count)
Packit Service a9274b
{
Packit Service a9274b
	char **bufs = cache->buf;
Packit Service a9274b
	char **buf_ptrs = cache->buf_ptr;
Packit Service a9274b
	unsigned int offset;
Packit Service a9274b
	unsigned int size;
Packit Service a9274b
	int i;
Packit Service a9274b
Packit Service a9274b
	cache->remained_count -= consumed_count;
Packit Service a9274b
Packit Service a9274b
	for (i = 0; i < cache->samples_per_frame; ++i) {
Packit Service a9274b
		offset = cache->bytes_per_sample * consumed_count;
Packit Service a9274b
		size = cache->bytes_per_sample * cache->remained_count;
Packit Service a9274b
		memmove(bufs[i], bufs[i] + offset, size);
Packit Service a9274b
		buf_ptrs[i] = bufs[i] + size;
Packit Service a9274b
	}
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
int frame_cache_init(struct frame_cache *cache, snd_pcm_access_t access,
Packit Service a9274b
		     unsigned int bytes_per_sample,
Packit Service a9274b
		     unsigned int samples_per_frame,
Packit Service a9274b
		     unsigned int frames_per_cache)
Packit Service a9274b
{
Packit Service a9274b
	cache->access = access;
Packit Service a9274b
	cache->remained_count = 0;
Packit Service a9274b
	cache->bytes_per_sample = bytes_per_sample;
Packit Service a9274b
	cache->samples_per_frame = samples_per_frame;
Packit Service a9274b
	cache->frames_per_cache = frames_per_cache;
Packit Service a9274b
Packit Service a9274b
	if (access == SND_PCM_ACCESS_RW_INTERLEAVED)
Packit Service a9274b
		cache->align_frames = align_frames_in_i;
Packit Service a9274b
	else if (access == SND_PCM_ACCESS_RW_NONINTERLEAVED)
Packit Service a9274b
		cache->align_frames = align_frames_in_n;
Packit Service a9274b
	else
Packit Service a9274b
		return -EINVAL;
Packit Service a9274b
Packit Service a9274b
	if (access == SND_PCM_ACCESS_RW_INTERLEAVED) {
Packit Service a9274b
		char *buf;
Packit Service a9274b
Packit Service a9274b
		buf = calloc(frames_per_cache,
Packit Service a9274b
			     bytes_per_sample * samples_per_frame);
Packit Service a9274b
		if (buf == NULL)
Packit Service a9274b
			goto nomem;
Packit Service a9274b
		cache->buf = buf;
Packit Service a9274b
		cache->buf_ptr = buf;
Packit Service a9274b
	} else {
Packit Service a9274b
		char **bufs = calloc(samples_per_frame, sizeof(*bufs));
Packit Service a9274b
		char **buf_ptrs = calloc(samples_per_frame, sizeof(*buf_ptrs));
Packit Service a9274b
		int i;
Packit Service a9274b
Packit Service a9274b
		cache->buf = bufs;
Packit Service a9274b
		cache->buf_ptr = buf_ptrs;
Packit Service a9274b
		if (bufs == NULL || buf_ptrs == NULL)
Packit Service a9274b
			goto nomem;
Packit Service a9274b
		for (i = 0; i < samples_per_frame; ++i) {
Packit Service a9274b
			bufs[i] = calloc(frames_per_cache, bytes_per_sample);
Packit Service a9274b
			if (bufs[i] == NULL)
Packit Service a9274b
				goto nomem;
Packit Service a9274b
			buf_ptrs[i] = bufs[i];
Packit Service a9274b
		}
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
	return 0;
Packit Service a9274b
Packit Service a9274b
nomem:
Packit Service a9274b
	frame_cache_destroy(cache);
Packit Service a9274b
	return -ENOMEM;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
void frame_cache_destroy(struct frame_cache *cache)
Packit Service a9274b
{
Packit Service a9274b
	if (cache->access == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
Packit Service a9274b
		char **bufs = cache->buf;
Packit Service a9274b
		if (bufs) {
Packit Service a9274b
			int i;
Packit Service a9274b
			for (i = 0; i < cache->samples_per_frame; ++i)
Packit Service a9274b
				free(bufs[i]);
Packit Service a9274b
		}
Packit Service a9274b
		free(cache->buf_ptr);
Packit Service a9274b
	}
Packit Service a9274b
	free(cache->buf);
Packit Service a9274b
	memset(cache, 0, sizeof(*cache));
Packit Service a9274b
}