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