kopia lustrzana https://github.com/windytan/slowrx
CirBuffer template class
rodzic
5dfd240c13
commit
da08acab8b
|
@ -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 ***/
|
||||
|
||||
|
|
24
src/common.h
24
src/common.h
|
@ -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 {
|
||||
|
|
62
src/input.cc
62
src/input.cc
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue