CirBuffer template class

dev
Oona Räisänen 2016-01-11 10:42:50 +02:00
rodzic 5dfd240c13
commit da08acab8b
4 zmienionych plików z 102 dodań i 55 usunięć

Wyświetl plik

@ -49,6 +49,71 @@ void ensure_dir_exists(std::string dir) {
}
}
template<class T> CirBuffer<T>::CirBuffer(int size) : m_data(size * 2), m_head(0), m_tail(0), m_fill_count(0), m_len(size) {
assert(size > 0);
}
template<class T> void CirBuffer<T>::moveHead(int n) {
m_head = (m_head + n) % m_len;
}
template<class T> void CirBuffer<T>::forward(int n) {
m_tail = (m_tail + n) % m_len;
m_fill_count -= n;
}
template<class T> int CirBuffer<T>::getFillCount() const {
return m_fill_count;
}
template<class T> int CirBuffer<T>::size() const {
return m_data.size();
}
template<class T> T CirBuffer<T>::at(int n) const {
int i = m_tail + n;
if (i < 0) {
i = m_len - (abs(i) % m_len);
} else {
i = i % m_len;
}
return m_data.at(i);
}
template<class T> void CirBuffer<T>::append(const std::vector<T>& input_data, int num_elems) {
assert(num_elems <= (int)input_data.size());
for (int i=0; i<num_elems; i++)
m_data.at((m_head + i) % m_len) = input_data[i];
// mirror
//for (int i=0; i<m_len; i++)
// m_data.at(m_len + i) = m_data.at(i);
m_head = (m_head + num_elems) % m_len;
m_fill_count += num_elems;
m_fill_count = std::min(m_fill_count, m_len);
}
template<class T> void CirBuffer<T>::append(T input_element) {
m_data.at(m_head) = input_element;
// mirror
m_data.at(m_head + m_len) = m_data.at(m_head);
m_head = (m_head + 1) % m_len;
m_fill_count += 1;
m_fill_count = std::min(m_fill_count, m_len);
}
// for the linker
template class CirBuffer<double>;
template class CirBuffer<float>;
/*** Gtk+ event handlers ***/

Wyświetl plik

@ -23,14 +23,24 @@ struct Tone {
using Wave = std::vector<double>;
using Melody = std::vector<Tone>;
struct CirBuffer {
Wave data;
int head;
int tail;
int fill_count;
template<class T> class CirBuffer {
public:
CirBuffer(int len);
void moveHead(int n);
int size() const;
void append(const std::vector<T>& input_data, int n);
void append(T input_element);
void forward(int n);
int getFillCount() const;
T at(int n) const;
private:
std::vector<T> m_data;
int m_head;
int m_tail;
int m_fill_count;
int m_len;
CirBuffer(size_t len) : data(len), head(0), tail(0), fill_count(0) {}
size_t size() { return data.size(); }
};
enum WindowType {

Wyświetl plik

@ -3,10 +3,8 @@
bool g_is_pa_initialized = false;
Input::Input() : m_cirbuf(CIRBUF_LEN*2), m_read_buffer(nullptr),
m_read_buffer_s16(nullptr), m_t(0) {
Input::Input() : m_cirbuf(CIRBUF_LEN), m_is_open(false), m_t(0) {
m_cirbuf.head = MOMENT_LEN/2;
}
void Input::openAudioFile (std::string fname) {
@ -155,7 +153,11 @@ int Input::PaCallback(const void *input, void *output,
m_read_buffer[i] = in[i * m_num_chans];
}
readBufferTransfer(framesread);
for (unsigned i = 0; i<READ_CHUNK_LEN; i++)
m_read_buffer[i] = in[i * m_num_chans];
m_cirbuf.append(m_read_buffer, framesread);
return 0;
}
@ -195,7 +197,7 @@ void Input::readMoreFromStdin() {
m_read_buffer.at(i) = m_read_buffer_s16.at(i) / 32768.0;
}
readBufferTransfer(framesread);
m_cirbuf.append(m_read_buffer, framesread);
}
std::vector<std::pair<int,std::string>> listPortaudioDevices() {
@ -221,51 +223,23 @@ int getDefaultPaDevice() {
return Pa_GetDefaultInputDevice();
}
void Input::readBufferTransfer (int framesread) {
{
std::lock_guard<std::mutex> guard(m_buffer_mutex);
int cirbuf_fits = std::min(CIRBUF_LEN - m_cirbuf.head, int(framesread));
for (int i=0; i<cirbuf_fits; i++)
m_cirbuf.data[m_cirbuf.head + i] = m_read_buffer[i];
// wrap around
if (framesread > cirbuf_fits) {
for (size_t i=0; i<(framesread - cirbuf_fits); i++)
m_cirbuf.data[i] = m_read_buffer[cirbuf_fits + i];
}
// mirror
for (size_t i=0; i<CIRBUF_LEN; i++)
m_cirbuf.data[CIRBUF_LEN + i] = m_cirbuf.data[i];
m_cirbuf.head = (m_cirbuf.head + framesread) % CIRBUF_LEN;
m_cirbuf.fill_count += framesread;
m_cirbuf.fill_count = std::min(int(m_cirbuf.fill_count), CIRBUF_LEN);
}
}
// move processing window
double Input::forward (unsigned nsamples) {
for (unsigned i = 0; i < nsamples; i++) {
double Input::forward (int nsamples) {
for (int i = 0; i < nsamples; i++) {
{
std::lock_guard<std::mutex> guard(m_buffer_mutex);
m_cirbuf.tail = (m_cirbuf.tail + 1) % CIRBUF_LEN;
m_cirbuf.fill_count -= 1;
m_cirbuf.forward(1);
}
if (m_cirbuf.fill_count < MOMENT_LEN) {
while (m_cirbuf.fill_count < MOMENT_LEN) {
if (m_stream_type == STREAM_TYPE_PA) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else if (m_stream_type == STREAM_TYPE_FILE) {
readMoreFromFile();
} else if (m_stream_type == STREAM_TYPE_STDIN) {
readMoreFromStdin();
}
while (m_cirbuf.getFillCount() < MOMENT_LEN) {
if (m_stream_type == STREAM_TYPE_PA) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else if (m_stream_type == STREAM_TYPE_FILE) {
readMoreFromFile();
} else if (m_stream_type == STREAM_TYPE_STDIN) {
readMoreFromStdin();
}
}
}

Wyświetl plik

@ -22,14 +22,12 @@ class Input {
void readMoreFromFile();
void readMoreFromStdin();
void readBufferTransfer (int);
double forward (unsigned);
double forward (int);
double forward ();
double forwardTime (double);
double get_t () const;
double getSamplerate () const;
bool isOpen () const;
bool isLive () const;
@ -47,7 +45,7 @@ class Input {
->PaCallback(input, output, frameCount, timeInfo, statusFlags);
}
CirBuffer m_cirbuf;
CirBuffer<float> m_cirbuf;
private: