1 /* 2 * Copyright (C) 2012 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 package org.drrickorang.loopback; 18 19 20 /** 21 * Non-blocking pipe where writer writes to the pipe using write() and read reads from the pipe 22 * using read(). Data in the pipe are stored in the short array "mBuffer". 23 * The write side of a pipe permits overruns; flow control is the caller's responsibility. 24 */ 25 26 public class PipeShort extends Pipe { 27 private int mFront; // writer's current position 28 private int mRear; // reader's current position 29 private final short mBuffer[]; // store that data in the pipe 30 private volatile int mVolatileRear; // used to keep rear synchronized 31 32 33 /** 34 * IMPORTANT: Since a signed integer is used to store mRear and mFront, their values should not 35 * exceed 2^31 - 1, or else overflows happens and the positions of read and mFront becomes 36 * incorrect. 37 */ PipeShort(int maxSamples)38 public PipeShort(int maxSamples) { 39 super(maxSamples); 40 mBuffer = new short[mMaxValues]; 41 } 42 43 44 /** 45 * offset must be >= 0. 46 * count is maximum number of bytes to copy, and must be >= 0. 47 * offset + count must be <= buffer.length. 48 * Return actual number of shorts copied, which will be >= 0. 49 */ write(short[] buffer, int offset, int count)50 public int write(short[] buffer, int offset, int count) { 51 // mask the upper bits to get the correct position in the pipe 52 int rear = mRear & (mMaxValues - 1); 53 int written = mMaxValues - rear; 54 if (written > count) { 55 written = count; 56 } 57 58 System.arraycopy(buffer, offset, mBuffer, rear, written); 59 if (rear + written == mMaxValues) { 60 if ((count -= written) > rear) { 61 count = rear; 62 } 63 if (count > 0) { 64 System.arraycopy(buffer, offset + written, mBuffer, 0, count); 65 written += count; 66 } 67 } 68 69 mRear += written; 70 mVolatileRear = mRear; 71 return written; 72 } 73 74 75 @Override read(short[] buffer, int offset, int count)76 public int read(short[] buffer, int offset, int count) { 77 int avail = availableToRead(); 78 if (avail <= 0) { 79 return avail; 80 } 81 82 // An overrun can occur from here on and be silently ignored, 83 // but it will be caught at next read() 84 if (count > avail) { 85 count = avail; 86 } 87 88 // mask the upper bits to get the correct position in the pipe 89 int front = mFront & (mMaxValues - 1); 90 int read = mMaxValues - front; 91 92 if (read > count) { 93 read = count; 94 } 95 96 // In particular, an overrun during the System.arraycopy will result in reading corrupt data 97 System.arraycopy(mBuffer, front, buffer, offset, read); 98 // We could re-read the rear pointer here to detect the corruption, but why bother? 99 if (front + read == mMaxValues) { 100 if ((count -= read) > front) { 101 count = front; 102 } 103 104 if (count > 0) { 105 System.arraycopy(mBuffer, 0, buffer, offset + read, count); 106 read += count; 107 } 108 } 109 110 mFront += read; 111 return read; 112 } 113 114 115 116 @Override availableToRead()117 public int availableToRead() { 118 int rear = mVolatileRear; 119 int avail = rear - mFront; 120 if (avail > mMaxValues) { 121 // Discard 1/16 of the most recent data in pipe to avoid another overrun immediately 122 int oldFront = mFront; 123 mFront = rear - mMaxValues + (mMaxValues >> 4); 124 mSamplesOverrun += mFront - oldFront; 125 ++mOverruns; 126 return OVERRUN; 127 } 128 129 return avail; 130 } 131 132 133 @Override flush()134 public void flush() { 135 mRear = mFront; 136 mVolatileRear = mFront; 137 } 138 139 } 140