// -*- mode: c++ -*- #ifndef BUFFER_H #define BUFFER_H #include "sbsms.h" #include "grain.h" #include #include using namespace std; namespace _sbsms_ { enum { initSampleBufLength = 8192, initGrainBufLength = 256, initRingBufferLength = 64 }; template class RingBuffer { public: RingBuffer(); ~RingBuffer(); long write(T a); T read(long k); T read(); long nReadable(); void advance(long n); void clear(); long readPos; long writePos; protected: T *buf; long length; }; /******************** RingBuffer ********************/ template RingBuffer :: RingBuffer() { length = initRingBufferLength; buf = (T*) calloc(2*length,sizeof(T)); readPos = 0; writePos = 0; } template RingBuffer :: ~RingBuffer() { free(buf); } template long RingBuffer :: write(T a) { if(writePos >= 2*length) { length *= 2; T *newBuf = (T*) calloc(2*length,sizeof(T)); memmove(newBuf,buf+readPos,(writePos-readPos)*sizeof(T)); free(buf); buf = newBuf; writePos -= readPos; readPos = 0; } buf[writePos++] = a; return 1; } template T RingBuffer :: read(long k) { return buf[k]; } template T RingBuffer :: read() { return buf[readPos]; } template long RingBuffer :: nReadable() { return writePos-readPos; } template void RingBuffer :: advance(long n) { readPos += n; if(readPos >= length) { memmove(buf,buf+readPos,(writePos-readPos)*sizeof(T)); writePos = writePos - readPos; readPos = 0; } } template void RingBuffer :: clear() { readPos = 0; writePos = 0; } class SampleBufBase { public: SampleBufBase() {}; virtual ~SampleBufBase() {}; virtual long read(audio *buf, long n)=0; }; /**************** SampleBuf ****************/ class grain; template class ArrayRingBuffer { public: ArrayRingBuffer(int N); virtual ~ArrayRingBuffer(); void clear(); void grow(long pos); void write(T *buf, long n); void write(grain *g, int h); void read(T *buf, long n); void advance(long n); long nReadable(); T *getReadBuf(); long readPos, writePos; int N; long length; T *buf; }; template ArrayRingBuffer :: ArrayRingBuffer(int N) { this->N = N; this->length = initSampleBufLength; this->buf = (T*)calloc(2*length,sizeof(T)); this->readPos = 0; this->writePos = 0; } template ArrayRingBuffer :: ~ArrayRingBuffer() { free(buf); } template void ArrayRingBuffer :: write(T *in, long n) { grow(n); if(in) memmove(buf+writePos,in,n*sizeof(T)); writePos += n; } template void ArrayRingBuffer :: grow(long n) { long pos = writePos+n; while(pos >= 2*length) { length *= 2; T *newBuf = (T*)calloc(2*length,sizeof(T)); memmove(newBuf,buf+readPos,(length-readPos)*sizeof(T)); free(buf); buf = newBuf; writePos -= readPos; pos -= readPos; readPos = 0; } } template void ArrayRingBuffer :: read(T *outBuf, long n) { n = max(0L,min(n,nReadable())); memmove(outBuf,buf+readPos,n*sizeof(T)); advance(n); } template long ArrayRingBuffer :: nReadable() { return max(0L,writePos-readPos); } template void ArrayRingBuffer :: advance(long n) { memset(buf+readPos,0,n*sizeof(T)); readPos += n; if(readPos >= length) { long endPos; endPos = writePos+N; memmove(buf,buf+readPos,(endPos-readPos)*sizeof(T)); memset(buf+readPos,0,((length<<1)-readPos)*sizeof(T)); writePos -= readPos; readPos = 0; } } template T *ArrayRingBuffer :: getReadBuf() { return (buf+readPos); } template void ArrayRingBuffer :: clear() { advance(writePos-readPos); } typedef ArrayRingBuffer