OSDN Git Service

axfer: add missing header file of unit test to distribution
[android-x86/external-alsa-utils.git] / axfer / frame-cache.c
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
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
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
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         if (access == SND_PCM_ACCESS_RW_INTERLEAVED)
54                 cache->align_frames = align_frames_in_i;
55         else if (access == SND_PCM_ACCESS_RW_NONINTERLEAVED)
56                 cache->align_frames = align_frames_in_n;
57         else
58                 return -EINVAL;
59         cache->access = access;
60
61         if (access == SND_PCM_ACCESS_RW_INTERLEAVED) {
62                 char *buf;
63
64                 buf = calloc(frames_per_cache,
65                              bytes_per_sample * samples_per_frame);
66                 if (buf == NULL)
67                         return -ENOMEM;
68                 cache->buf = buf;
69                 cache->buf_ptr = buf;
70         } else {
71                 char **bufs;
72                 char **buf_ptrs;
73                 int i;
74
75                 bufs = calloc(samples_per_frame, sizeof(*bufs));
76                 if (bufs == NULL)
77                         return -ENOMEM;
78                 buf_ptrs = calloc(samples_per_frame, sizeof(*buf_ptrs));
79                 if (buf_ptrs == NULL)
80                         return -ENOMEM;
81                 for (i = 0; i < samples_per_frame; ++i) {
82                         bufs[i] = calloc(frames_per_cache, bytes_per_sample);
83                         if (bufs[i] == NULL)
84                                 return -ENOMEM;
85                         buf_ptrs[i] = bufs[i];
86                 }
87                 cache->buf = bufs;
88                 cache->buf_ptr = buf_ptrs;
89         }
90
91         cache->remained_count = 0;
92         cache->bytes_per_sample = bytes_per_sample;
93         cache->samples_per_frame = samples_per_frame;
94         cache->frames_per_cache = frames_per_cache;
95
96         return 0;
97 }
98
99 void frame_cache_destroy(struct frame_cache *cache)
100 {
101         if (cache->access == SND_PCM_ACCESS_RW_NONINTERLEAVED) {
102                 int i;
103                 for (i = 0; i < cache->samples_per_frame; ++i) {
104                         char **bufs = cache->buf;
105                         free(bufs[i]);
106                 }
107                 free(cache->buf_ptr);
108         }
109         free(cache->buf);
110         memset(cache, 0, sizeof(*cache));
111 }