Changeset 1346 for portaudio/branches/v19-devel/src/common/pa_ringbuffer.c
- Timestamp:
- 02/20/08 05:09:20 (10 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
portaudio/branches/v19-devel/src/common/pa_ringbuffer.c
r1320 r1346 8 8 * modified for SMP safety on Linux by Leland Lucius 9 9 * also, allowed for const where possible 10 * modified for multiple-byte-sized data elements by Sven Fischer 11 * 10 12 * Note that this is safe only for a single-thread reader and a 11 13 * single-thread writer. … … 60 62 /*************************************************************************** 61 63 * Initialize FIFO. 62 * numBytesmust be power of 2, returns -1 if not.64 * elementCount must be power of 2, returns -1 if not. 63 65 */ 64 long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long numBytes, void *dataPtr )65 { 66 if( (( numBytes-1) & numBytes) != 0) return -1; /* Not Power of two. */67 rbuf->bufferSize = numBytes;66 long PaUtil_InitializeRingBuffer( PaUtilRingBuffer *rbuf, long elementSizeBytes, long elementCount, void *dataPtr ) 67 { 68 if( ((elementCount-1) & elementCount) != 0) return -1; /* Not Power of two. */ 69 rbuf->bufferSize = elementCount; 68 70 rbuf->buffer = (char *)dataPtr; 69 71 PaUtil_FlushRingBuffer( rbuf ); 70 rbuf->bigMask = (numBytes*2)-1; 71 rbuf->smallMask = (numBytes)-1; 72 rbuf->bigMask = (elementCount*2)-1; 73 rbuf->smallMask = (elementCount)-1; 74 rbuf->elementSizeBytes = elementSizeBytes; 72 75 return 0; 73 76 } 74 77 75 78 /*************************************************************************** 76 ** Return number of bytes available for reading. */79 ** Return number of elements available for reading. */ 77 80 long PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf ) 78 81 { … … 81 84 } 82 85 /*************************************************************************** 83 ** Return number of bytes available for writing. */86 ** Return number of elements available for writing. */ 84 87 long PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf ) 85 88 { … … 99 102 ** If the region is contiguous, size2 will be zero. 100 103 ** If non-contiguous, size2 will be the size of second region. 101 ** Returns room available to be written or numBytes, whichever is smaller.102 */ 103 long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long numBytes,104 ** Returns room available to be written or elementCount, whichever is smaller. 105 */ 106 long PaUtil_GetRingBufferWriteRegions( PaUtilRingBuffer *rbuf, long elementCount, 104 107 void **dataPtr1, long *sizePtr1, 105 108 void **dataPtr2, long *sizePtr2 ) … … 107 110 long index; 108 111 long available = PaUtil_GetRingBufferWriteAvailable( rbuf ); 109 if( numBytes > available ) numBytes= available;112 if( elementCount > available ) elementCount = available; 110 113 /* Check to see if write is not contiguous. */ 111 114 index = rbuf->writeIndex & rbuf->smallMask; 112 if( (index + numBytes) > rbuf->bufferSize )115 if( (index + elementCount) > rbuf->bufferSize ) 113 116 { 114 117 /* Write data in two blocks that wrap the buffer. */ 115 118 long firstHalf = rbuf->bufferSize - index; 116 *dataPtr1 = &rbuf->buffer[index ];119 *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes]; 117 120 *sizePtr1 = firstHalf; 118 121 *dataPtr2 = &rbuf->buffer[0]; 119 *sizePtr2 = numBytes- firstHalf;120 } 121 else 122 { 123 *dataPtr1 = &rbuf->buffer[index ];124 *sizePtr1 = numBytes;122 *sizePtr2 = elementCount - firstHalf; 123 } 124 else 125 { 126 *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes]; 127 *sizePtr1 = elementCount; 125 128 *dataPtr2 = NULL; 126 129 *sizePtr2 = 0; 127 130 } 128 return numBytes;129 } 130 131 132 /*************************************************************************** 133 */ 134 long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long numBytes)131 return elementCount; 132 } 133 134 135 /*************************************************************************** 136 */ 137 long PaUtil_AdvanceRingBufferWriteIndex( PaUtilRingBuffer *rbuf, long elementCount ) 135 138 { 136 139 /* we need to ensure that previous writes are seen before we update the write index */ 137 140 PaUtil_WriteMemoryBarrier(); 138 return rbuf->writeIndex = (rbuf->writeIndex + numBytes) & rbuf->bigMask;141 return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask; 139 142 } 140 143 … … 143 146 ** If the region is contiguous, size2 will be zero. 144 147 ** If non-contiguous, size2 will be the size of second region. 145 ** Returns room available to be written or numBytes, whichever is smaller.146 */ 147 long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long numBytes,148 ** Returns room available to be written or elementCount, whichever is smaller. 149 */ 150 long PaUtil_GetRingBufferReadRegions( PaUtilRingBuffer *rbuf, long elementCount, 148 151 void **dataPtr1, long *sizePtr1, 149 152 void **dataPtr2, long *sizePtr2 ) … … 151 154 long index; 152 155 long available = PaUtil_GetRingBufferReadAvailable( rbuf ); 153 if( numBytes > available ) numBytes= available;156 if( elementCount > available ) elementCount = available; 154 157 /* Check to see if read is not contiguous. */ 155 158 index = rbuf->readIndex & rbuf->smallMask; 156 if( (index + numBytes) > rbuf->bufferSize )159 if( (index + elementCount) > rbuf->bufferSize ) 157 160 { 158 161 /* Write data in two blocks that wrap the buffer. */ 159 162 long firstHalf = rbuf->bufferSize - index; 160 *dataPtr1 = &rbuf->buffer[index ];163 *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes]; 161 164 *sizePtr1 = firstHalf; 162 165 *dataPtr2 = &rbuf->buffer[0]; 163 *sizePtr2 = numBytes- firstHalf;164 } 165 else 166 { 167 *dataPtr1 = &rbuf->buffer[index ];168 *sizePtr1 = numBytes;166 *sizePtr2 = elementCount - firstHalf; 167 } 168 else 169 { 170 *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes]; 171 *sizePtr1 = elementCount; 169 172 *dataPtr2 = NULL; 170 173 *sizePtr2 = 0; 171 174 } 172 return numBytes;173 } 174 /*************************************************************************** 175 */ 176 long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long numBytes)175 return elementCount; 176 } 177 /*************************************************************************** 178 */ 179 long PaUtil_AdvanceRingBufferReadIndex( PaUtilRingBuffer *rbuf, long elementCount ) 177 180 { 178 181 /* we need to ensure that previous writes are always seen before updating the index. */ 179 182 PaUtil_WriteMemoryBarrier(); 180 return rbuf->readIndex = (rbuf->readIndex + numBytes) & rbuf->bigMask;181 } 182 183 /*************************************************************************** 184 ** Return bytes written. */185 long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long numBytes)183 return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask; 184 } 185 186 /*************************************************************************** 187 ** Return elements written. */ 188 long PaUtil_WriteRingBuffer( PaUtilRingBuffer *rbuf, const void *data, long elementCount ) 186 189 { 187 190 long size1, size2, numWritten; 188 191 void *data1, *data2; 189 numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );192 numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 ); 190 193 if( size2 > 0 ) 191 194 { 192 195 193 memcpy( data1, data, size1 );194 data = ((char *)data) + size1 ;195 memcpy( data2, data, size2 );196 } 197 else 198 { 199 memcpy( data1, data, size1 );196 memcpy( data1, data, size1*rbuf->elementSizeBytes ); 197 data = ((char *)data) + size1*rbuf->elementSizeBytes; 198 memcpy( data2, data, size2*rbuf->elementSizeBytes ); 199 } 200 else 201 { 202 memcpy( data1, data, size1*rbuf->elementSizeBytes ); 200 203 } 201 204 PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten ); … … 204 207 205 208 /*************************************************************************** 206 ** Return bytes read. */207 long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long numBytes)209 ** Return elements read. */ 210 long PaUtil_ReadRingBuffer( PaUtilRingBuffer *rbuf, void *data, long elementCount ) 208 211 { 209 212 long size1, size2, numRead; 210 213 void *data1, *data2; 211 numRead = PaUtil_GetRingBufferReadRegions( rbuf, numBytes, &data1, &size1, &data2, &size2 );214 numRead = PaUtil_GetRingBufferReadRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 ); 212 215 if( size2 > 0 ) 213 216 { 214 memcpy( data, data1, size1 );215 data = ((char *)data) + size1 ;216 memcpy( data, data2, size2 );217 } 218 else 219 { 220 memcpy( data, data1, size1 );217 memcpy( data, data1, size1*rbuf->elementSizeBytes ); 218 data = ((char *)data) + size1*rbuf->elementSizeBytes; 219 memcpy( data, data2, size2*rbuf->elementSizeBytes ); 220 } 221 else 222 { 223 memcpy( data, data1, size1*rbuf->elementSizeBytes ); 221 224 } 222 225 PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
