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