started making samplerate and buffer size configurable for audio device selection

This commit is contained in:
Dave Griffiths 2022-09-30 21:08:53 +01:00
parent a2b77951ca
commit fb8d607e2d
16 changed files with 112 additions and 124 deletions

View File

@ -26,7 +26,9 @@ audio_thread::audio_thread(process_thread &p) :
m_process_thread(p), m_process_thread(p),
m_brain_mutex(p.m_brain_mutex), m_brain_mutex(p.m_brain_mutex),
m_stereo_mode(false), m_stereo_mode(false),
m_mic_mode(false) m_mic_mode(false),
m_bufsize(2048),
m_samplerate(44100)
{ {
start_audio(); start_audio();
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
@ -48,8 +50,7 @@ audio_thread::~audio_thread() {
void audio_thread::start_audio() { void audio_thread::start_audio() {
if (m_audio_device!=NULL) delete m_audio_device; if (m_audio_device!=NULL) delete m_audio_device;
m_audio_device = new audio_device("samplebrain",48000,2048); m_audio_device = new audio_device("samplebrain",m_samplerate,m_bufsize);
//m_audio_device = new audio_device("samplebrain",48000,2048*4);
m_audio_device->m_client.set_callback(run_audio, this); m_audio_device->m_client.set_callback(run_audio, this);
} }

View File

@ -24,8 +24,8 @@
namespace spiralcore { namespace spiralcore {
class audio_thread { class audio_thread {
public: public:
audio_thread(process_thread &p); audio_thread(process_thread &p);
~audio_thread(); ~audio_thread();
@ -38,7 +38,7 @@ public:
renderer *m_right_renderer; renderer *m_right_renderer;
block_stream *m_block_stream; block_stream *m_block_stream;
private: private:
void start_audio(); void start_audio();
OSC_server m_osc; OSC_server m_osc;
@ -46,6 +46,8 @@ private:
pthread_mutex_t* m_brain_mutex; pthread_mutex_t* m_brain_mutex;
bool m_stereo_mode; bool m_stereo_mode;
bool m_mic_mode; bool m_mic_mode;
}; u32 m_bufsize;
u32 m_samplerate;
};
} }

View File

@ -63,82 +63,82 @@ void process_thread::process() {
string name = cmd.m_name; string name = cmd.m_name;
//cerr<<name<<endl; //cerr<<name<<endl;
if (name=="/load_sample") { if (name=="/load_sample") {
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_source.load_sound(cmd.get_string(0),brain::MIX); m_source.load_sound(cmd.get_string(0),brain::MIX);
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
} }
if (name=="/delete_sample") { if (name=="/delete_sample") {
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_source.delete_sound(cmd.get_string(0)); m_source.delete_sound(cmd.get_string(0));
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
} }
if (name=="/activate_sound") { if (name=="/activate_sound") {
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_source.activate_sound(cmd.get_string(0),1); m_source.activate_sound(cmd.get_string(0),1);
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
} }
if (name=="/deactivate_sound") { if (name=="/deactivate_sound") {
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_source.activate_sound(cmd.get_string(0),0); m_source.activate_sound(cmd.get_string(0),0);
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
} }
if (name=="/source_block_size") { if (name=="/source_block_size") {
m_source_block_size = cmd.get_int(0); m_source_block_size = cmd.get_int(0);
} }
if (name=="/source_overlap") { if (name=="/source_overlap") {
m_source_overlap = m_source_block_size*cmd.get_float(0); m_source_overlap = m_source_block_size*cmd.get_float(0);
} }
if (name=="/generate_brain") { if (name=="/generate_brain") {
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_source.init(m_source_block_size, m_source_overlap, m_window_type); m_source.init(m_source_block_size, m_source_overlap, m_window_type);
search_params p(1,0,0,100,0); search_params p(1,0,0,100,0);
m_source.build_synapses_fixed(p); m_source.build_synapses_fixed(p);
m_left_renderer->reset(); m_left_renderer->reset();
m_right_renderer->reset(); m_right_renderer->reset();
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
} }
if (name=="/load_target") { if (name=="/load_target") {
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_left_target.clear_sounds(); m_left_target.clear_sounds();
m_left_target.load_sound(cmd.get_string(0),brain::LEFT); m_left_target.load_sound(cmd.get_string(0),brain::LEFT);
m_right_target.clear_sounds(); m_right_target.clear_sounds();
m_right_target.load_sound(cmd.get_string(0),brain::RIGHT); m_right_target.load_sound(cmd.get_string(0),brain::RIGHT);
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
} }
if (name=="/target_block_size") { if (name=="/target_block_size") {
m_target_block_size = cmd.get_int(0); m_target_block_size = cmd.get_int(0);
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type); m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
} }
if (name=="/target_overlap") { if (name=="/target_overlap") {
m_target_overlap = m_target_block_size*cmd.get_float(0); m_target_overlap = m_target_block_size*cmd.get_float(0);
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type); m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
} }
if (name=="/generate_target") { if (name=="/generate_target") {
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_left_target.init(m_target_block_size, m_target_overlap, m_target_window_type); m_left_target.init(m_target_block_size, m_target_overlap, m_target_window_type);
m_right_target.init(m_target_block_size, m_target_overlap, m_target_window_type); m_right_target.init(m_target_block_size, m_target_overlap, m_target_window_type);
// probably elsewhere // probably elsewhere
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type); m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
} }
if (name=="/window_type") { if (name=="/window_type") {
m_window_type=(window::type)cmd.get_int(0); m_window_type=(window::type)cmd.get_int(0);
} }
if (name=="/target_window_type") { if (name=="/target_window_type") {
m_target_window_type=(window::type)cmd.get_int(0); m_target_window_type=(window::type)cmd.get_int(0);
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type); m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
} }
if (name=="/load_brain") { if (name=="/load_brain") {
load_source(cmd.get_string(0)); load_source(cmd.get_string(0));
} }
if (name=="/save_brain") { if (name=="/save_brain") {
save_source(cmd.get_string(0)); save_source(cmd.get_string(0));
} }
if (name=="/load_session") { if (name=="/load_session") {
load_session(cmd.get_string(0)); load_session(cmd.get_string(0));
} }
if (name=="/save_session") { if (name=="/save_session") {
save_session(cmd.get_string(0)); save_session(cmd.get_string(0));
} }
} }
#ifdef WIN32 #ifdef WIN32
@ -181,9 +181,6 @@ void process_thread::load_session(const std::string &filename) {
ifs||m_source_block_size||m_source_overlap; ifs||m_source_block_size||m_source_overlap;
ifs||m_target_block_size||m_target_overlap; ifs||m_target_block_size||m_target_overlap;
ifs||m_window_type||m_target_window_type; ifs||m_window_type||m_target_window_type;
cerr<<"loading window type session "<<m_target_window_type<<endl;
ifs||m_source; ifs||m_source;
ifs||m_left_target; ifs||m_left_target;
ifs||m_right_target; ifs||m_right_target;
@ -200,9 +197,6 @@ void process_thread::save_session(const std::string &filename) {
ofs||(*m_right_renderer); ofs||(*m_right_renderer);
ofs||m_source_block_size||m_source_overlap; ofs||m_source_block_size||m_source_overlap;
ofs||m_target_block_size||m_target_overlap; ofs||m_target_block_size||m_target_overlap;
cerr<<"saving window type session "<<m_target_window_type<<endl;
ofs||m_window_type||m_target_window_type; ofs||m_window_type||m_target_window_type;
ofs||m_source; ofs||m_source;
ofs||m_left_target; ofs||m_left_target;

View File

@ -77,7 +77,7 @@ block::block(u64 id, const string &filename, const sample &pcm, u32 rate, const
m_orig_filename(filename), m_orig_filename(filename),
m_usage(0) m_usage(0)
{ {
init_fft(m_pcm.get_length()); init_fft(m_pcm.get_length(),rate);
assert(m_mfcc_proc!=NULL); assert(m_mfcc_proc!=NULL);
assert(m_fftw!=NULL); assert(m_fftw!=NULL);
@ -97,12 +97,12 @@ block::block(u64 id, const string &filename, const sample &pcm, u32 rate, const
} }
void block::init_fft(u32 block_size) { void block::init_fft(u32 block_size, u32 rate) {
if (m_fftw == NULL || m_fftw->m_length!=block_size) { if (m_fftw == NULL || m_fftw->m_length!=block_size) {
if (m_fftw == NULL) delete m_fftw; if (m_fftw == NULL) delete m_fftw;
m_fftw = new FFT(block_size,100); m_fftw = new FFT(block_size,rate,100);
if (m_mfcc_proc == NULL) delete m_mfcc_proc; if (m_mfcc_proc == NULL) delete m_mfcc_proc;
m_mfcc_proc = new Aquila::Mfcc(block_size); m_mfcc_proc = new Aquila::Mfcc(block_size,rate);
} }
} }

View File

@ -38,7 +38,7 @@ namespace spiralcore {
// returns distance based on ratio of fft-mfcc values // returns distance based on ratio of fft-mfcc values
double compare(const block &other, const search_params &params) const; double compare(const block &other, const search_params &params) const;
static void init_fft(u32 block_size); static void init_fft(u32 block_size, u32 rate);
static bool unit_test(); static bool unit_test();
const sample &get_pcm() const { return m_pcm; } const sample &get_pcm() const { return m_pcm; }

View File

@ -377,34 +377,6 @@ void brain::deplete_usage() {
} }
} }
// take another brain and rebuild this brain from bits of that one
// (presumably this one is made from a single sample)
/*void brain::resynth(const string &filename, const brain &other, const search_params &params){
sample out((m_block_size-m_overlap)*m_blocks.size());
out.zero();
u32 pos = 0;
u32 count = 0;
cerr<<other.m_blocks.size()<<" brain blocks..."<<endl;
cerr<<endl;
for (vector<block>::iterator i=m_blocks.begin(); i!=m_blocks.end(); ++i) {
cerr<<'\r';
cerr<<"searching: "<<count/float(m_blocks.size())*100;
u32 index = other.search(*i, params);
//cerr<<index<<endl;
out.mul_mix(other.get_block_pcm(index),pos,0.2);
if (count%1000==0) {
audio_device::save_sample(filename,out);
}
++count;
pos += (m_block_size-m_overlap);
}
audio_device::save_sample(filename,out);
}
*/
ios &spiralcore::operator||(ios &s, brain::sound &b) { ios &spiralcore::operator||(ios &s, brain::sound &b) {
u32 version=1; u32 version=1;
string id("brain::sound"); string id("brain::sound");

View File

@ -24,8 +24,9 @@ using namespace std;
static const int MAX_FFT_LENGTH = 4096; static const int MAX_FFT_LENGTH = 4096;
FFT::FFT(u32 length, u32 bins) : FFT::FFT(u32 length, u32 rate, u32 bins) :
m_length(length), m_length(length),
m_rate(rate),
m_num_bins(bins), m_num_bins(bins),
m_in(new double[length]), m_in(new double[length]),
m_spectrum(new fftw_complex[length]), m_spectrum(new fftw_complex[length]),
@ -35,26 +36,19 @@ FFT::FFT(u32 length, u32 bins) :
m_plan = fftw_plan_dft_r2c_1d(m_length, m_in, m_spectrum, FFTW_ESTIMATE); m_plan = fftw_plan_dft_r2c_1d(m_length, m_in, m_spectrum, FFTW_ESTIMATE);
} }
FFT::~FFT() FFT::~FFT() {
{
delete[] m_in; delete[] m_in;
fftw_destroy_plan(m_plan); fftw_destroy_plan(m_plan);
} }
void FFT::impulse2freq(const float *imp) void FFT::impulse2freq(const float *imp) {
{
unsigned int i; unsigned int i;
for (i=0; i<m_length; i++) {
for (i=0; i<m_length; i++) m_in[i] = imp[i];
{ }
m_in[i] = imp[i];
}
fftw_execute(m_plan); fftw_execute(m_plan);
} }
static const float SRATE = 44100;
float FFT::calculate_dominant_freq() { float FFT::calculate_dominant_freq() {
double highest = 0; double highest = 0;
u32 index = 0; u32 index = 0;
@ -65,7 +59,7 @@ float FFT::calculate_dominant_freq() {
highest=t; highest=t;
} }
} }
float freq = index * (SRATE/(float)m_length); float freq = index * (m_rate/(float)m_length);
if (freq<0.01) freq=0.01; if (freq<0.01) freq=0.01;
return freq; return freq;
} }

View File

@ -27,7 +27,7 @@ namespace spiralcore {
class FFT class FFT
{ {
public: public:
FFT(u32 length, u32 num_bins); FFT(u32 length, u32 rate, u32 num_bins);
~FFT(); ~FFT();
void impulse2freq(const float *imp); void impulse2freq(const float *imp);
void calculate_bins(); void calculate_bins();
@ -35,6 +35,7 @@ namespace spiralcore {
fftw_plan m_plan; fftw_plan m_plan;
u32 m_length; u32 m_length;
u32 m_rate;
u32 m_num_bins; u32 m_num_bins;
double *m_in; double *m_in;
fftw_complex *m_spectrum; fftw_complex *m_spectrum;

View File

@ -26,7 +26,7 @@ namespace Aquila
{ {
//auto spectrum = m_fft->fft(source); //auto spectrum = m_fft->fft(source);
Aquila::MelFilterBank bank(44100, m_inputSize); Aquila::MelFilterBank bank(m_sampleRate, m_inputSize);
auto filterOutput = bank.applyAll(spectrum); auto filterOutput = bank.applyAll(spectrum);
Aquila::Dct dct; Aquila::Dct dct;

View File

@ -59,8 +59,9 @@ namespace Aquila
* *
* @param inputSize input length (common to all inputs) * @param inputSize input length (common to all inputs)
*/ */
Mfcc(std::size_t inputSize): Mfcc(std::size_t inputSize, unsigned int sampleRate):
m_inputSize(inputSize)//, m_fft(FftFactory::getFft(inputSize)) m_inputSize(inputSize), // m_fft(FftFactory::getFft(inputSize))
m_sampleRate(sampleRate)
{ {
} }
@ -71,7 +72,8 @@ namespace Aquila
* Number of samples in each processed input. * Number of samples in each processed input.
*/ */
const std::size_t m_inputSize; const std::size_t m_inputSize;
const unsigned int m_sampleRate;
/** /**
* FFT calculator. * FFT calculator.
*/ */

View File

@ -27,7 +27,8 @@ audio_device::audio_device(const string &clientname, u32 samplerate, u32 buffer_
left_in(buffer_size), left_in(buffer_size),
right_in(buffer_size), right_in(buffer_size),
m_recording(false), m_recording(false),
m_record_filename("") m_record_filename(""),
m_samplerate(samplerate)
{ {
portaudio_client::device_options opt; portaudio_client::device_options opt;
opt.buffer_size = buffer_size; opt.buffer_size = buffer_size;
@ -46,7 +47,7 @@ void audio_device::save_sample(const string &filename, const sample s) {
SF_INFO sfinfo; SF_INFO sfinfo;
sfinfo.format=SF_FORMAT_WAV | SF_FORMAT_FLOAT; sfinfo.format=SF_FORMAT_WAV | SF_FORMAT_FLOAT;
sfinfo.frames=s.get_length(); sfinfo.frames=s.get_length();
sfinfo.samplerate=44100; sfinfo.samplerate=m_samplerate;
sfinfo.channels=1; sfinfo.channels=1;
sfinfo.sections=1; sfinfo.sections=1;
sfinfo.seekable=0; sfinfo.seekable=0;

View File

@ -24,8 +24,8 @@ class graph;
namespace spiralcore { namespace spiralcore {
class audio_device { class audio_device {
public: public:
audio_device(const string &clientname, u32 samplerate, u32 buffer_size); audio_device(const string &clientname, u32 samplerate, u32 buffer_size);
void start_graph(graph *graph); void start_graph(graph *graph);
@ -42,15 +42,15 @@ public:
portaudio_client m_client; portaudio_client m_client;
static void save_sample(const std::string &filename, const sample s); void save_sample(const std::string &filename, const sample s);
private: private:
bool m_recording; bool m_recording;
std::string m_record_filename; std::string m_record_filename;
sample m_record_buffer_left; sample m_record_buffer_left;
sample m_record_buffer_right; sample m_record_buffer_right;
u32 m_record_counter; u32 m_record_counter;
u32 m_samplerate;
}; };
} }

View File

@ -21,7 +21,6 @@
bool portaudio_client::m_attached = false; bool portaudio_client::m_attached = false;
long unsigned int portaudio_client::m_buffer_size = 0; long unsigned int portaudio_client::m_buffer_size = 0;
long unsigned int portaudio_client::m_sample_rate = 44100;
void (*portaudio_client::run_callback)(void*, unsigned int buf_size)=NULL; void (*portaudio_client::run_callback)(void*, unsigned int buf_size)=NULL;
void *portaudio_client::run_context = NULL; void *portaudio_client::run_context = NULL;
const float *portaudio_client::m_right_data=NULL; const float *portaudio_client::m_right_data=NULL;
@ -42,6 +41,23 @@ portaudio_client::~portaudio_client() {
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
vector<string> portaudio_client::sniff_devices() {
vector<string> ret;
int numDevices = Pa_GetDeviceCount();
if(numDevices < 0) {
// this is an error I guess
return ret;
}
const PaDeviceInfo *deviceInfo;
for(int i=0; i<numDevices; i++) {
deviceInfo = Pa_GetDeviceInfo(i);
ret.push_back(deviceInfo->name);
}
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////////
bool portaudio_client::attach(const string &client_name, const device_options &dopt) { bool portaudio_client::attach(const string &client_name, const device_options &dopt) {
if (m_attached) return true; if (m_attached) return true;

View File

@ -42,6 +42,7 @@ class portaudio_client
unsigned int out_channels; unsigned int out_channels;
}; };
vector<string> sniff_devices();
bool attach(const string &client_name, const device_options &dopt); bool attach(const string &client_name, const device_options &dopt);
void detach(); void detach();
bool is_attached() { return m_attached; } bool is_attached() { return m_attached; }
@ -60,7 +61,6 @@ class portaudio_client
private: private:
static long unsigned int m_buffer_size; static long unsigned int m_buffer_size;
static long unsigned int m_sample_rate;
static bool m_attached; static bool m_attached;
static const float *m_right_data; static const float *m_right_data;

View File

@ -34,6 +34,10 @@ void status::sound_item_refresh() {
lo_send(m_address,"/sound-item-refresh",""); lo_send(m_address,"/sound-item-refresh","");
} }
void status::add_audio_device(const std::string &name) {
lo_send(m_address,"/add_audio_device",name.c_str());
}
void status::update(const char *msg, ...) { void status::update(const char *msg, ...) {
va_list args; va_list args;
va_start(args, msg); va_start(args, msg);

View File

@ -24,11 +24,12 @@ namespace spiralcore {
class status { class status {
public: public:
static void _update(const std::string &msg); static void _update(const std::string &msg);
static void update(const char *msg, ...); static void update(const char *msg, ...);
static void sound_item(const std::string &name, const std::string &colour); static void sound_item(const std::string &name, const std::string &colour);
static void sound_item_refresh(); static void sound_item_refresh();
static lo_address m_address; static void add_audio_device(const std::string &name);
static lo_address m_address;
}; };
} }