• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // frame-cache.c - maintainer of cache for data frame.
4 //
5 // Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6 //
7 // Licensed under the terms of the GNU General Public License, version 2.
8 
9 #include "frame-cache.h"
10 
align_frames_in_i(struct frame_cache * cache,unsigned int consumed_count)11 static void align_frames_in_i(struct frame_cache *cache,
12 			      unsigned int consumed_count)
13 {
14 	char *buf = cache->buf;
15 	unsigned int offset;
16 	unsigned int size;
17 
18 	cache->remained_count -= consumed_count;
19 
20 	offset = cache->bytes_per_sample * cache->samples_per_frame *
21 		 consumed_count;
22 	size = cache->bytes_per_sample * cache->samples_per_frame *
23 	       cache->remained_count;
24 	memmove(buf, buf + offset, size);
25 
26 	cache->buf_ptr = buf + size;
27 }
28 
align_frames_in_n(struct frame_cache * cache,unsigned int consumed_count)29 static void align_frames_in_n(struct frame_cache *cache,
30 			      unsigned int consumed_count)
31 {
32 	char **bufs = cache->buf;
33 	char **buf_ptrs = cache->buf_ptr;
34 	unsigned int offset;
35 	unsigned int size;
36 	int i;
37 
38 	cache->remained_count -= consumed_count;
39 
40 	for (i = 0; i < cache->samples_per_frame; ++i) {
41 		offset = cache->bytes_per_sample * consumed_count;
42 		size = cache->bytes_per_sample * cache->remained_count;
43 		memmove(bufs[i], bufs[i] + offset, size);
44 		buf_ptrs[i] = bufs[i] + size;
45 	}
46 }
47 
frame_cache_init(struct frame_cache * cache,snd_pcm_access_t access,unsigned int bytes_per_sample,unsigned int samples_per_frame,unsigned int frames_per_cache)48 int frame_cache_init(struct frame_cache *cache, snd_pcm_access_t access,
49 		     unsigned int bytes_per_sample,
50 		     unsigned int samples_per_frame,
51 		     unsigned int frames_per_cache)
52 {
53 	cache->access = access;
54 	cache->remained_count = 0;
55 	cache->bytes_per_sample = bytes_per_sample;
56 	cache->samples_per_frame = samples_per_frame;
57 	cache->frames_per_cache = frames_per_cache;
58 
59 	if (access == SND_PCM_ACCESS_RW_INTERLEAVED)
60 		cache->align_frames = align_frames_in_i;
61 	else if (access == SND_PCM_ACCESS_RW_NONINTERLEAVED)
62 		cache->align_frames = align_frames_in_n;
63 	else
64 		return -EINVAL;
65 
66 	if (access == SND_PCM_ACCESS_RW_INTERLEAVED) {
67 		char *buf;
68 
69 		buf = calloc(frames_per_cache,
70 			     bytes_per_sample * samples_per_frame);
71 		if (buf == NULL)
72 			goto nomem;
73 		cache->buf = buf;
74 		cache->buf_ptr = buf;
75 	} else {
76 		char **bufs = calloc(samples_per_frame, sizeof(*bufs));
77 		char **buf_ptrs = calloc(samples_per_frame, sizeof(*buf_ptrs));
78 		int i;
79 
80 		cache->buf = bufs;
81 		cache->buf_ptr = buf_ptrs;
82 		if (bufs == NULL || buf_ptrs == NULL)
83 			goto nomem;
84 		for (i = 0; i < samples_per_frame; ++i) {
85 			bufs[i] = calloc(frames_per_cache, bytes_per_sample);
86 			if (bufs[i] == NULL)
87 				goto nomem;
88 			buf_ptrs[i] = bufs[i];
89 		}
90 	}
91 
92 
93 	return 0;
94 
95 nomem:
96 	frame_cache_destroy(cache);
97 	return -ENOMEM;
98 }
99 
frame_cache_destroy(struct frame_cache * cache)100 void frame_cache_destroy(struct frame_cache *cache)
101 {
102 	if (cache->access == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
103 		char **bufs = cache->buf;
104 		if (bufs) {
105 			int i;
106 			for (i = 0; i < cache->samples_per_frame; ++i)
107 				free(bufs[i]);
108 		}
109 		free(cache->buf_ptr);
110 	}
111 	free(cache->buf);
112 	memset(cache, 0, sizeof(*cache));
113 }
114