Blame axfer/test/generator.c

Packit Service a9274b
// SPDX-License-Identifier: GPL-2.0
Packit Service a9274b
//
Packit Service a9274b
// allocator.h - a header of a generator for test with buffers of PCM frames.
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 "generator.h"
Packit Service a9274b
Packit Service a9274b
#include <stdlib.h>
Packit Service a9274b
Packit Service a9274b
#include <sys/types.h>
Packit Service a9274b
#include <sys/stat.h>
Packit Service a9274b
#include <fcntl.h>
Packit Service a9274b
Packit Service a9274b
#include <unistd.h>
Packit Service a9274b
Packit Service a9274b
int generator_context_init(struct test_generator *gen,
Packit Service a9274b
			   uint64_t access_mask, uint64_t sample_format_mask,
Packit Service a9274b
			   unsigned int min_samples_per_frame,
Packit Service a9274b
			   unsigned int max_samples_per_frame,
Packit Service a9274b
			   unsigned int min_frame_count,
Packit Service a9274b
			   unsigned int max_frame_count,
Packit Service a9274b
			   unsigned int step_frame_count,
Packit Service a9274b
			   unsigned int private_size)
Packit Service a9274b
{
Packit Service a9274b
	gen->fd = open("/dev/urandom", O_RDONLY);
Packit Service a9274b
	if (gen->fd < 0)
Packit Service a9274b
		return -errno;
Packit Service a9274b
Packit Service a9274b
	gen->private_data = malloc(private_size);
Packit Service a9274b
	if (gen->private_data == NULL)
Packit Service a9274b
		return -ENOMEM;
Packit Service a9274b
	memset(gen->private_data, 0, private_size);
Packit Service a9274b
Packit Service a9274b
	gen->access_mask = access_mask;
Packit Service a9274b
	gen->sample_format_mask = sample_format_mask;
Packit Service a9274b
	gen->min_samples_per_frame = min_samples_per_frame;
Packit Service a9274b
	gen->max_samples_per_frame = max_samples_per_frame;
Packit Service a9274b
	gen->min_frame_count = min_frame_count;
Packit Service a9274b
	gen->max_frame_count = max_frame_count;
Packit Service a9274b
	gen->step_frame_count = step_frame_count;
Packit Service a9274b
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void *allocate_buf(snd_pcm_access_t access,
Packit Service a9274b
			  snd_pcm_format_t sample_format,
Packit Service a9274b
			  unsigned int samples_per_frame,
Packit Service a9274b
			  unsigned int frame_count)
Packit Service a9274b
{
Packit Service a9274b
	unsigned int bytes_per_sample;
Packit Service a9274b
Packit Service a9274b
	bytes_per_sample = snd_pcm_format_physical_width(sample_format) / 8;
Packit Service a9274b
Packit Service a9274b
	return calloc(samples_per_frame * frame_count, bytes_per_sample);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void *allocate_vector(snd_pcm_access_t access,
Packit Service a9274b
			     snd_pcm_format_t sample_format,
Packit Service a9274b
			     unsigned int samples_per_frame,
Packit Service a9274b
			     unsigned int frame_count)
Packit Service a9274b
{
Packit Service a9274b
	unsigned int bytes_per_sample;
Packit Service a9274b
	char **bufs;
Packit Service a9274b
	int i;
Packit Service a9274b
Packit Service a9274b
	bytes_per_sample = snd_pcm_format_physical_width(sample_format) / 8;
Packit Service a9274b
Packit Service a9274b
	bufs = calloc(samples_per_frame, sizeof(char *));
Packit Service a9274b
	if (bufs == NULL)
Packit Service a9274b
		return NULL;
Packit Service a9274b
Packit Service a9274b
	for (i = 0; i < samples_per_frame; ++i) {
Packit Service a9274b
		bufs[i] = calloc(frame_count, bytes_per_sample);
Packit Service a9274b
		if (bufs[i] == NULL) {
Packit Service a9274b
			for (; i >= 0; --i)
Packit Service a9274b
				free(bufs[i]);
Packit Service a9274b
			free(bufs);
Packit Service a9274b
			return NULL;
Packit Service a9274b
		}
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	return bufs;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int fill_buf(int fd, void *frame_buffer, snd_pcm_access_t access,
Packit Service a9274b
		    snd_pcm_format_t sample_format,
Packit Service a9274b
		    unsigned int samples_per_frame, unsigned int frame_count)
Packit Service a9274b
{
Packit Service a9274b
	unsigned int size;
Packit Service a9274b
	int len;
Packit Service a9274b
Packit Service a9274b
	size = snd_pcm_format_physical_width(sample_format) / 8 *
Packit Service a9274b
						samples_per_frame * frame_count;
Packit Service a9274b
	while (size > 0) {
Packit Service a9274b
		len = read(fd, frame_buffer, size);
Packit Service a9274b
		if (len < 0)
Packit Service a9274b
			return len;
Packit Service a9274b
		size -= len;
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int fill_vector(int fd, void *frame_buffer, snd_pcm_access_t access,
Packit Service a9274b
		       snd_pcm_format_t sample_format,
Packit Service a9274b
		       unsigned int samples_per_frame, unsigned int frame_count)
Packit Service a9274b
{
Packit Service a9274b
	char **bufs = frame_buffer;
Packit Service a9274b
	unsigned int size;
Packit Service a9274b
	int len;
Packit Service a9274b
	int i;
Packit Service a9274b
Packit Service a9274b
	for (i = 0; i < samples_per_frame; ++i) {
Packit Service a9274b
		size = frame_count *
Packit Service a9274b
			snd_pcm_format_physical_width(sample_format) / 8;
Packit Service a9274b
Packit Service a9274b
		while (size > 0) {
Packit Service a9274b
			len = read(fd, bufs[i], size);
Packit Service a9274b
			if (len < 0)
Packit Service a9274b
				return len;
Packit Service a9274b
			size -= len;
Packit Service a9274b
		}
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void deallocate_buf(void *frame_buffer, unsigned int samples_per_frame)
Packit Service a9274b
{
Packit Service a9274b
	free(frame_buffer);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void deallocate_vector(void *frame_buffer,
Packit Service a9274b
			      unsigned int samples_per_frame)
Packit Service a9274b
{
Packit Service a9274b
	char **bufs = frame_buffer;
Packit Service a9274b
	int i;
Packit Service a9274b
Packit Service a9274b
	for (i = 0; i < samples_per_frame; ++i)
Packit Service a9274b
		free(bufs[i]);
Packit Service a9274b
Packit Service a9274b
	free(bufs);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int test_frame_count(struct test_generator *gen,
Packit Service a9274b
			    snd_pcm_access_t access,
Packit Service a9274b
			    snd_pcm_format_t sample_format,
Packit Service a9274b
			    unsigned int samples_per_frame)
Packit Service a9274b
{
Packit Service a9274b
	void *(*allocator)(snd_pcm_access_t access,
Packit Service a9274b
			   snd_pcm_format_t sample_format,
Packit Service a9274b
			   unsigned int samples_per_frame,
Packit Service a9274b
			   unsigned int frame_count);
Packit Service a9274b
	int (*fill)(int fd, void *frame_buffer, snd_pcm_access_t access,
Packit Service a9274b
		    snd_pcm_format_t sample_format,
Packit Service a9274b
		    unsigned int samples_per_frame, unsigned int frame_count);
Packit Service a9274b
	void (*deallocator)(void *frame_buffer, unsigned int samples_per_frame);
Packit Service a9274b
	void *frame_buffer;
Packit Service a9274b
	int i;
Packit Service a9274b
	int err = 0;
Packit Service a9274b
Packit Service a9274b
	if (access != SND_PCM_ACCESS_RW_NONINTERLEAVED) {
Packit Service a9274b
		allocator = allocate_buf;
Packit Service a9274b
		fill = fill_buf;
Packit Service a9274b
		deallocator = deallocate_buf;
Packit Service a9274b
	} else {
Packit Service a9274b
		allocator = allocate_vector;
Packit Service a9274b
		fill = fill_vector;
Packit Service a9274b
		deallocator = deallocate_vector;
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	frame_buffer = allocator(access, sample_format, samples_per_frame,
Packit Service a9274b
				 gen->max_frame_count);
Packit Service a9274b
	if (frame_buffer == NULL)
Packit Service a9274b
		return -ENOMEM;
Packit Service a9274b
Packit Service a9274b
	err = fill(gen->fd, frame_buffer, access, sample_format,
Packit Service a9274b
		   samples_per_frame, gen->max_frame_count);
Packit Service a9274b
	if (err < 0)
Packit Service a9274b
		goto end;
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
	for (i = gen->min_frame_count;
Packit Service a9274b
	     i <= gen->max_frame_count; i += gen->step_frame_count) {
Packit Service a9274b
		err = gen->cb(gen, access ,sample_format, samples_per_frame,
Packit Service a9274b
			      frame_buffer, i);
Packit Service a9274b
		if (err < 0)
Packit Service a9274b
			break;
Packit Service a9274b
	}
Packit Service a9274b
end:
Packit Service a9274b
	deallocator(frame_buffer, samples_per_frame);
Packit Service a9274b
Packit Service a9274b
	return err;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int test_samples_per_frame(struct test_generator *gen,
Packit Service a9274b
				  snd_pcm_access_t access,
Packit Service a9274b
				  snd_pcm_format_t sample_format)
Packit Service a9274b
{
Packit Service a9274b
	int i;
Packit Service a9274b
	int err = 0;
Packit Service a9274b
Packit Service a9274b
	for (i = gen->min_samples_per_frame;
Packit Service a9274b
	     i <= gen->max_samples_per_frame; ++i) {
Packit Service a9274b
		err = test_frame_count(gen, access, sample_format, i);
Packit Service a9274b
		if (err < 0)
Packit Service a9274b
			break;
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	return err;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int test_sample_format(struct test_generator *gen,
Packit Service a9274b
			      snd_pcm_access_t access)
Packit Service a9274b
{
Packit Service a9274b
	int i;
Packit Service a9274b
	int err = 0;
Packit Service a9274b
Packit Service a9274b
	for (i = 0; i <= SND_PCM_FORMAT_LAST; ++i) {
Packit Service a9274b
		if (!((1ull << i) & gen->sample_format_mask))
Packit Service a9274b
			continue;
Packit Service a9274b
Packit Service a9274b
		err = test_samples_per_frame(gen, access, i);
Packit Service a9274b
		if (err < 0)
Packit Service a9274b
			break;
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	return err;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int test_access(struct test_generator *gen)
Packit Service a9274b
{
Packit Service a9274b
	int i;
Packit Service a9274b
	int err = 0;
Packit Service a9274b
Packit Service a9274b
	for (i = 0; i <= SND_PCM_ACCESS_LAST; ++i) {
Packit Service a9274b
		if (!((1ull << i) & gen->access_mask))
Packit Service a9274b
			continue;
Packit Service a9274b
Packit Service a9274b
		err = test_sample_format(gen, i);
Packit Service a9274b
		if (err < 0)
Packit Service a9274b
			break;
Packit Service a9274b
	}
Packit Service a9274b
	return err;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
int generator_context_run(struct test_generator *gen, generator_cb_t cb)
Packit Service a9274b
{
Packit Service a9274b
	gen->cb = cb;
Packit Service a9274b
	return test_access(gen);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
void generator_context_destroy(struct test_generator *gen)
Packit Service a9274b
{
Packit Service a9274b
	free(gen->private_data);
Packit Service a9274b
	close(gen->fd);
Packit Service a9274b
}