mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-10 17:37:45 +02:00
266 lines
4.4 KiB
C++
266 lines
4.4 KiB
C++
// -*- mode: c++ -*-
|
|
#ifndef BUFFER_H
|
|
#define BUFFER_H
|
|
|
|
#include "sbsms.h"
|
|
#include "grain.h"
|
|
#include <stdlib.h>
|
|
#include <list>
|
|
using namespace std;
|
|
|
|
namespace _sbsms_ {
|
|
|
|
enum {
|
|
initSampleBufLength = 8192,
|
|
initGrainBufLength = 256,
|
|
initRingBufferLength = 64
|
|
};
|
|
|
|
template <class T>
|
|
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 <class T>
|
|
RingBuffer<T> :: RingBuffer()
|
|
{
|
|
length = initRingBufferLength;
|
|
buf = (T*) calloc(2*length,sizeof(T));
|
|
readPos = 0;
|
|
writePos = 0;
|
|
}
|
|
|
|
template <class T>
|
|
RingBuffer<T> :: ~RingBuffer()
|
|
{
|
|
free(buf);
|
|
}
|
|
|
|
template <class T>
|
|
long RingBuffer<T> :: 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 <class T>
|
|
T RingBuffer<T> :: read(long k)
|
|
{
|
|
return buf[k];
|
|
}
|
|
|
|
template <class T>
|
|
T RingBuffer<T> :: read()
|
|
{
|
|
return buf[readPos];
|
|
}
|
|
|
|
template <class T>
|
|
long RingBuffer<T> :: nReadable()
|
|
{
|
|
return writePos-readPos;
|
|
}
|
|
|
|
template <class T>
|
|
void RingBuffer<T> :: advance(long n)
|
|
{
|
|
readPos += n;
|
|
if(readPos >= length) {
|
|
memmove(buf,buf+readPos,(writePos-readPos)*sizeof(T));
|
|
writePos = writePos - readPos;
|
|
readPos = 0;
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
void RingBuffer<T> :: clear()
|
|
{
|
|
readPos = 0;
|
|
writePos = 0;
|
|
}
|
|
|
|
class SampleBufBase {
|
|
public:
|
|
SampleBufBase() {};
|
|
virtual ~SampleBufBase() {};
|
|
virtual long read(audio *buf, long n)=0;
|
|
};
|
|
|
|
/****************
|
|
|
|
SampleBuf
|
|
|
|
****************/
|
|
|
|
class grain;
|
|
|
|
template<class T>
|
|
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<class T>
|
|
ArrayRingBuffer<T> :: ArrayRingBuffer(int N)
|
|
{
|
|
this->N = N;
|
|
this->length = initSampleBufLength;
|
|
this->buf = (T*)calloc(2*length,sizeof(T));
|
|
this->readPos = 0;
|
|
this->writePos = 0;
|
|
}
|
|
|
|
template<class T>
|
|
ArrayRingBuffer<T> :: ~ArrayRingBuffer()
|
|
{
|
|
free(buf);
|
|
}
|
|
|
|
template<class T>
|
|
void ArrayRingBuffer<T> :: write(T *in, long n)
|
|
{
|
|
grow(n);
|
|
if(in) memmove(buf+writePos,in,n*sizeof(T));
|
|
writePos += n;
|
|
}
|
|
|
|
template<class T>
|
|
void ArrayRingBuffer<T> :: 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<class T>
|
|
void ArrayRingBuffer<T> :: read(T *outBuf, long n)
|
|
{
|
|
n = max(0L,min(n,nReadable()));
|
|
memmove(outBuf,buf+readPos,n*sizeof(T));
|
|
advance(n);
|
|
}
|
|
|
|
template<class T>
|
|
long ArrayRingBuffer<T> :: nReadable()
|
|
{
|
|
return max(0L,writePos-readPos);
|
|
}
|
|
|
|
template<class T>
|
|
void ArrayRingBuffer<T> :: 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<class T>
|
|
T *ArrayRingBuffer<T> :: getReadBuf()
|
|
{
|
|
return (buf+readPos);
|
|
}
|
|
|
|
template<class T>
|
|
void ArrayRingBuffer<T> :: clear()
|
|
{
|
|
advance(writePos-readPos);
|
|
}
|
|
|
|
typedef ArrayRingBuffer<audio> SampleBuf;
|
|
|
|
class GrainBuf {
|
|
public:
|
|
GrainBuf(int N, int h, int N2, int type);
|
|
~GrainBuf();
|
|
long write(audio *buf, long n);
|
|
void write(grain *g);
|
|
void advance(long n);
|
|
long nReadable();
|
|
void clear();
|
|
grain* read(long k);
|
|
void reference(grain *g);
|
|
void forget(grain *g);
|
|
audio *getWindowFFT();
|
|
long readPos;
|
|
long writePos;
|
|
protected:
|
|
audio *iBuf;
|
|
grain **buf;
|
|
long length;
|
|
long N2;
|
|
long h;
|
|
long overlap;
|
|
long xOffset;
|
|
long iBufWritePos;
|
|
GrainAllocator grainAllocator;
|
|
};
|
|
|
|
class Mixer : public SampleBufBase {
|
|
public:
|
|
Mixer(SampleBufBase *, SampleBuf *);
|
|
~Mixer() {}
|
|
virtual long read(audio *buf, long n);
|
|
protected:
|
|
SampleBufBase *b1;
|
|
SampleBuf *b2;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|