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 11static 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 29static 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 unsigned 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 48int 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 unsigned 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 95nomem: 96 frame_cache_destroy(cache); 97 return -ENOMEM; 98} 99 100void 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 unsigned 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