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