1b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson/* 2b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Copyright (C) 2011 The Android Open Source Project 3b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * 4b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Licensed under the Apache License, Version 2.0 (the "License"); 5b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * you may not use this file except in compliance with the License. 6b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * You may obtain a copy of the License at 7b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * 8b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * http://www.apache.org/licenses/LICENSE-2.0 9b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * 10b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * Unless required by applicable law or agreed to in writing, software 11b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * distributed under the License is distributed on an "AS IS" BASIS, 12b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * See the License for the specific language governing permissions and 14b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson * limitations under the License. 15b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson */ 16b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 17b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#include "ring_buffer.h" 18b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 19b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson#include "integral_types.h" 20b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 21b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonnamespace video_editing { 22b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 23b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonvoid RingBuffer::Init(int size, int num_channels, int num_readers) { 24b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson size_ = size; 25b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ = num_channels; 26b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_readers_ = num_readers; 27b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson temp_read_buffer_size_ = 1024; 28b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson initialized_ = true; 29b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson Reset(); 30b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 31b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 32b83ad73794088498d6d38cd3b4fc9311f505d051Hugo HudsonRingBuffer::RingBuffer() 33b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson : initialized_(false), samples_(NULL), 34b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_readers_(0), temp_read_buffer_(NULL) { 35b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 36b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 37b83ad73794088498d6d38cd3b4fc9311f505d051Hugo HudsonRingBuffer::~RingBuffer() { 38b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson delete[] samples_; 39b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson delete[] temp_read_buffer_; 40b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 41b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 42b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonvoid RingBuffer::Reset() { 43b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson delete[] samples_; 44b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson samples_ = new float[size_ * num_channels_]; 45b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memset(samples_, 0, 46b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson size_ * num_channels_ * sizeof(samples_[0])); 47b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 48b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson temp_read_buffer_size_ = 1024; 49b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson delete[] temp_read_buffer_; 50b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson temp_read_buffer_ = new float[temp_read_buffer_size_ * num_channels_]; 51b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memset(temp_read_buffer_, 0, 52b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson temp_read_buffer_size_ * num_channels_ * sizeof(samples_[0])); 53b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson readers_.clear(); 54b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson for (int i = 0; i < num_readers_; ++i) { 55b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson readers_.push_back(0LL); 56b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 57b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson head_logical_ = 0LL; 58b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson head_ = 0; 59b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 60b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 61b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonint RingBuffer::available(int reader) const { 62b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson return head_logical_ - readers_[reader]; 63b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 64b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 65b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonint RingBuffer::overhead() const { 66b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int64 tail = GetTail(); 67b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson return tail + size_ - head_logical_; 68b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 69b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 70b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonint64 RingBuffer::GetTail() const { 71b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson return *min_element(readers_.begin(), readers_.end()); 72b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 73b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 74b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonint64 RingBuffer::Tell(int reader) const { 75b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson return readers_[reader]; 76b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 77b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 78b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonvoid RingBuffer::Seek(int reader, int64 position) { 79b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson readers_[reader] = position; 80b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 81b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 82b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonvoid RingBuffer::Write(const float* samples, int num_frames) { 83b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson if (!num_frames) { 84b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson return; 85b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 86b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson if (head_ + num_frames <= size_) { 87b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(samples_ + head_ * num_channels_, samples, 88b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_frames * num_channels_ * sizeof(samples[0])); 89b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson head_ += num_frames; 90b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } else { 91b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int overhead = size_ - head_; 92b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(samples_ + head_ * num_channels_, samples, 93b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * overhead * sizeof(samples[0])); 94b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson head_ = num_frames - overhead; 95b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(samples_, samples + overhead * num_channels_, 96b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * head_ * sizeof(samples[0])); 97b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 98b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson head_logical_ += num_frames; 99b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 100b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 101b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonvoid RingBuffer::Copy(int reader, float* destination, int num_frames) const { 102b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int pos = Tell(reader) % size_; 103b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson if (pos + num_frames <= size_) { 104b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(destination, samples_ + pos * num_channels_, 105b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * num_frames * sizeof(destination[0])); 106b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } else { 107b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int wrapped = size_ - pos; 108b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(destination, samples_ + pos * num_channels_, 109b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * wrapped * sizeof(destination[0])); 110b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int remaining = num_frames - wrapped; 111b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(destination + wrapped * num_channels_, samples_, 112b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * remaining * sizeof(destination[0])); 113b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 114b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 115b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 116b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonfloat* RingBuffer::GetPointer(int reader, int num_frames) { 117b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int pos = Tell(reader) % size_; 118b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson if (pos + num_frames <= size_) { 119b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson return samples_ + pos * num_channels_; 120b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } else { 121b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson if (num_frames > temp_read_buffer_size_) { 122b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson temp_read_buffer_size_ = num_frames; 123b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson delete[] temp_read_buffer_; 124b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson temp_read_buffer_ = 125b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson new float[temp_read_buffer_size_ * num_channels_]; // NOLINT 126b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 127b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson Copy(reader, temp_read_buffer_, num_frames); 128b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson return temp_read_buffer_; 129b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 130b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 131b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 132b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudsonvoid RingBuffer::MergeBack(int reader, const float* source, int num_frames) { 133b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson // If the source pointer is not the temporary buffer, 134b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson // data updates were performed in place, so there is nothing to do. 135b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson // Otherwise, copy samples from the temp buffer back to the ring buffer. 136b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson if (source == temp_read_buffer_) { 137b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int pos = Tell(reader) % size_; 138b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson if (pos + num_frames <= size_) { 139b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(samples_ + (pos * num_channels_), source, 140b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * num_frames * sizeof(source[0])); 141b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } else { 142b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int wrapped = size_ - pos; 143b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(samples_ + (pos * num_channels_), source, 144b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * wrapped * sizeof(source[0])); 145b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson int remaining = num_frames - wrapped; 146b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson memcpy(samples_, source + (wrapped * num_channels_), 147b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson num_channels_ * remaining * sizeof(source[0])); 148b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 149b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson } 150b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} 151b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson 152b83ad73794088498d6d38cd3b4fc9311f505d051Hugo Hudson} // namespace video_editing 153