mirror of
https://gitlab.com/then-try-this/samplebrain.git
synced 2025-05-11 10:07:21 +00:00
started making samplerate and buffer size configurable for audio device selection
This commit is contained in:
parent
a2b77951ca
commit
fb8d607e2d
@ -26,7 +26,9 @@ audio_thread::audio_thread(process_thread &p) :
|
||||
m_process_thread(p),
|
||||
m_brain_mutex(p.m_brain_mutex),
|
||||
m_stereo_mode(false),
|
||||
m_mic_mode(false)
|
||||
m_mic_mode(false),
|
||||
m_bufsize(2048),
|
||||
m_samplerate(44100)
|
||||
{
|
||||
start_audio();
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
@ -48,8 +50,7 @@ audio_thread::~audio_thread() {
|
||||
|
||||
void audio_thread::start_audio() {
|
||||
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",48000,2048*4);
|
||||
m_audio_device = new audio_device("samplebrain",m_samplerate,m_bufsize);
|
||||
m_audio_device->m_client.set_callback(run_audio, this);
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@
|
||||
|
||||
namespace spiralcore {
|
||||
|
||||
class audio_thread {
|
||||
public:
|
||||
class audio_thread {
|
||||
public:
|
||||
audio_thread(process_thread &p);
|
||||
~audio_thread();
|
||||
|
||||
@ -38,7 +38,7 @@ public:
|
||||
renderer *m_right_renderer;
|
||||
block_stream *m_block_stream;
|
||||
|
||||
private:
|
||||
private:
|
||||
void start_audio();
|
||||
|
||||
OSC_server m_osc;
|
||||
@ -46,6 +46,8 @@ private:
|
||||
pthread_mutex_t* m_brain_mutex;
|
||||
bool m_stereo_mode;
|
||||
bool m_mic_mode;
|
||||
};
|
||||
u32 m_bufsize;
|
||||
u32 m_samplerate;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -63,82 +63,82 @@ void process_thread::process() {
|
||||
string name = cmd.m_name;
|
||||
//cerr<<name<<endl;
|
||||
if (name=="/load_sample") {
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.load_sound(cmd.get_string(0),brain::MIX);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.load_sound(cmd.get_string(0),brain::MIX);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
}
|
||||
if (name=="/delete_sample") {
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.delete_sound(cmd.get_string(0));
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.delete_sound(cmd.get_string(0));
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
}
|
||||
if (name=="/activate_sound") {
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.activate_sound(cmd.get_string(0),1);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.activate_sound(cmd.get_string(0),1);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
}
|
||||
if (name=="/deactivate_sound") {
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.activate_sound(cmd.get_string(0),0);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.activate_sound(cmd.get_string(0),0);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
}
|
||||
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") {
|
||||
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") {
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.init(m_source_block_size, m_source_overlap, m_window_type);
|
||||
search_params p(1,0,0,100,0);
|
||||
m_source.build_synapses_fixed(p);
|
||||
m_left_renderer->reset();
|
||||
m_right_renderer->reset();
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_source.init(m_source_block_size, m_source_overlap, m_window_type);
|
||||
search_params p(1,0,0,100,0);
|
||||
m_source.build_synapses_fixed(p);
|
||||
m_left_renderer->reset();
|
||||
m_right_renderer->reset();
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
}
|
||||
if (name=="/load_target") {
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_left_target.clear_sounds();
|
||||
m_left_target.load_sound(cmd.get_string(0),brain::LEFT);
|
||||
m_right_target.clear_sounds();
|
||||
m_right_target.load_sound(cmd.get_string(0),brain::RIGHT);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
m_left_target.clear_sounds();
|
||||
m_left_target.load_sound(cmd.get_string(0),brain::LEFT);
|
||||
m_right_target.clear_sounds();
|
||||
m_right_target.load_sound(cmd.get_string(0),brain::RIGHT);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
}
|
||||
if (name=="/target_block_size") {
|
||||
m_target_block_size = cmd.get_int(0);
|
||||
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
|
||||
m_target_block_size = cmd.get_int(0);
|
||||
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
|
||||
}
|
||||
if (name=="/target_overlap") {
|
||||
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_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);
|
||||
}
|
||||
if (name=="/generate_target") {
|
||||
pthread_mutex_lock(m_brain_mutex);
|
||||
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);
|
||||
// probably elsewhere
|
||||
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
|
||||
pthread_mutex_unlock(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_right_target.init(m_target_block_size, m_target_overlap, m_target_window_type);
|
||||
// probably elsewhere
|
||||
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
|
||||
pthread_mutex_unlock(m_brain_mutex);
|
||||
}
|
||||
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") {
|
||||
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_target_window_type=(window::type)cmd.get_int(0);
|
||||
m_block_stream->init(m_target_block_size, m_target_overlap, m_target_window_type);
|
||||
}
|
||||
if (name=="/load_brain") {
|
||||
load_source(cmd.get_string(0));
|
||||
load_source(cmd.get_string(0));
|
||||
}
|
||||
if (name=="/save_brain") {
|
||||
save_source(cmd.get_string(0));
|
||||
save_source(cmd.get_string(0));
|
||||
}
|
||||
if (name=="/load_session") {
|
||||
load_session(cmd.get_string(0));
|
||||
load_session(cmd.get_string(0));
|
||||
}
|
||||
if (name=="/save_session") {
|
||||
save_session(cmd.get_string(0));
|
||||
save_session(cmd.get_string(0));
|
||||
}
|
||||
}
|
||||
#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_target_block_size||m_target_overlap;
|
||||
ifs||m_window_type||m_target_window_type;
|
||||
|
||||
cerr<<"loading window type session "<<m_target_window_type<<endl;
|
||||
|
||||
ifs||m_source;
|
||||
ifs||m_left_target;
|
||||
ifs||m_right_target;
|
||||
@ -200,9 +197,6 @@ void process_thread::save_session(const std::string &filename) {
|
||||
ofs||(*m_right_renderer);
|
||||
ofs||m_source_block_size||m_source_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_source;
|
||||
ofs||m_left_target;
|
||||
|
@ -77,7 +77,7 @@ block::block(u64 id, const string &filename, const sample &pcm, u32 rate, const
|
||||
m_orig_filename(filename),
|
||||
m_usage(0)
|
||||
{
|
||||
init_fft(m_pcm.get_length());
|
||||
init_fft(m_pcm.get_length(),rate);
|
||||
assert(m_mfcc_proc!=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) 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;
|
||||
m_mfcc_proc = new Aquila::Mfcc(block_size);
|
||||
m_mfcc_proc = new Aquila::Mfcc(block_size,rate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ namespace spiralcore {
|
||||
// returns distance based on ratio of fft-mfcc values
|
||||
double compare(const block &other, const search_params ¶ms) const;
|
||||
|
||||
static void init_fft(u32 block_size);
|
||||
static void init_fft(u32 block_size, u32 rate);
|
||||
static bool unit_test();
|
||||
|
||||
const sample &get_pcm() const { return m_pcm; }
|
||||
|
@ -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 ¶ms){
|
||||
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) {
|
||||
u32 version=1;
|
||||
string id("brain::sound");
|
||||
|
@ -24,8 +24,9 @@ using namespace std;
|
||||
|
||||
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_rate(rate),
|
||||
m_num_bins(bins),
|
||||
m_in(new double[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);
|
||||
}
|
||||
|
||||
FFT::~FFT()
|
||||
{
|
||||
FFT::~FFT() {
|
||||
delete[] m_in;
|
||||
fftw_destroy_plan(m_plan);
|
||||
}
|
||||
|
||||
void FFT::impulse2freq(const float *imp)
|
||||
{
|
||||
void FFT::impulse2freq(const float *imp) {
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<m_length; i++)
|
||||
{
|
||||
m_in[i] = imp[i];
|
||||
}
|
||||
|
||||
for (i=0; i<m_length; i++) {
|
||||
m_in[i] = imp[i];
|
||||
}
|
||||
fftw_execute(m_plan);
|
||||
}
|
||||
|
||||
static const float SRATE = 44100;
|
||||
|
||||
float FFT::calculate_dominant_freq() {
|
||||
double highest = 0;
|
||||
u32 index = 0;
|
||||
@ -65,7 +59,7 @@ float FFT::calculate_dominant_freq() {
|
||||
highest=t;
|
||||
}
|
||||
}
|
||||
float freq = index * (SRATE/(float)m_length);
|
||||
float freq = index * (m_rate/(float)m_length);
|
||||
if (freq<0.01) freq=0.01;
|
||||
return freq;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace spiralcore {
|
||||
class FFT
|
||||
{
|
||||
public:
|
||||
FFT(u32 length, u32 num_bins);
|
||||
FFT(u32 length, u32 rate, u32 num_bins);
|
||||
~FFT();
|
||||
void impulse2freq(const float *imp);
|
||||
void calculate_bins();
|
||||
@ -35,6 +35,7 @@ namespace spiralcore {
|
||||
|
||||
fftw_plan m_plan;
|
||||
u32 m_length;
|
||||
u32 m_rate;
|
||||
u32 m_num_bins;
|
||||
double *m_in;
|
||||
fftw_complex *m_spectrum;
|
||||
|
@ -26,7 +26,7 @@ namespace Aquila
|
||||
{
|
||||
//auto spectrum = m_fft->fft(source);
|
||||
|
||||
Aquila::MelFilterBank bank(44100, m_inputSize);
|
||||
Aquila::MelFilterBank bank(m_sampleRate, m_inputSize);
|
||||
auto filterOutput = bank.applyAll(spectrum);
|
||||
|
||||
Aquila::Dct dct;
|
||||
|
@ -59,8 +59,9 @@ namespace Aquila
|
||||
*
|
||||
* @param inputSize input length (common to all inputs)
|
||||
*/
|
||||
Mfcc(std::size_t inputSize):
|
||||
m_inputSize(inputSize)//, m_fft(FftFactory::getFft(inputSize))
|
||||
Mfcc(std::size_t inputSize, unsigned int sampleRate):
|
||||
m_inputSize(inputSize), // m_fft(FftFactory::getFft(inputSize))
|
||||
m_sampleRate(sampleRate)
|
||||
{
|
||||
}
|
||||
|
||||
@ -71,7 +72,8 @@ namespace Aquila
|
||||
* Number of samples in each processed input.
|
||||
*/
|
||||
const std::size_t m_inputSize;
|
||||
|
||||
const unsigned int m_sampleRate;
|
||||
|
||||
/**
|
||||
* FFT calculator.
|
||||
*/
|
||||
|
@ -27,7 +27,8 @@ audio_device::audio_device(const string &clientname, u32 samplerate, u32 buffer_
|
||||
left_in(buffer_size),
|
||||
right_in(buffer_size),
|
||||
m_recording(false),
|
||||
m_record_filename("")
|
||||
m_record_filename(""),
|
||||
m_samplerate(samplerate)
|
||||
{
|
||||
portaudio_client::device_options opt;
|
||||
opt.buffer_size = buffer_size;
|
||||
@ -46,7 +47,7 @@ void audio_device::save_sample(const string &filename, const sample s) {
|
||||
SF_INFO sfinfo;
|
||||
sfinfo.format=SF_FORMAT_WAV | SF_FORMAT_FLOAT;
|
||||
sfinfo.frames=s.get_length();
|
||||
sfinfo.samplerate=44100;
|
||||
sfinfo.samplerate=m_samplerate;
|
||||
sfinfo.channels=1;
|
||||
sfinfo.sections=1;
|
||||
sfinfo.seekable=0;
|
||||
|
@ -24,8 +24,8 @@ class graph;
|
||||
|
||||
namespace spiralcore {
|
||||
|
||||
class audio_device {
|
||||
public:
|
||||
class audio_device {
|
||||
public:
|
||||
audio_device(const string &clientname, u32 samplerate, u32 buffer_size);
|
||||
|
||||
void start_graph(graph *graph);
|
||||
@ -42,15 +42,15 @@ public:
|
||||
|
||||
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;
|
||||
std::string m_record_filename;
|
||||
sample m_record_buffer_left;
|
||||
sample m_record_buffer_right;
|
||||
u32 m_record_counter;
|
||||
|
||||
};
|
||||
u32 m_samplerate;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
bool portaudio_client::m_attached = false;
|
||||
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_context = 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) {
|
||||
if (m_attached) return true;
|
||||
|
||||
|
@ -42,6 +42,7 @@ class portaudio_client
|
||||
unsigned int out_channels;
|
||||
};
|
||||
|
||||
vector<string> sniff_devices();
|
||||
bool attach(const string &client_name, const device_options &dopt);
|
||||
void detach();
|
||||
bool is_attached() { return m_attached; }
|
||||
@ -60,7 +61,6 @@ class portaudio_client
|
||||
private:
|
||||
|
||||
static long unsigned int m_buffer_size;
|
||||
static long unsigned int m_sample_rate;
|
||||
static bool m_attached;
|
||||
|
||||
static const float *m_right_data;
|
||||
|
@ -34,6 +34,10 @@ void status::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, ...) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
|
@ -24,11 +24,12 @@ namespace spiralcore {
|
||||
|
||||
class status {
|
||||
public:
|
||||
static void _update(const std::string &msg);
|
||||
static void update(const char *msg, ...);
|
||||
static void sound_item(const std::string &name, const std::string &colour);
|
||||
static void sound_item_refresh();
|
||||
static lo_address m_address;
|
||||
static void _update(const std::string &msg);
|
||||
static void update(const char *msg, ...);
|
||||
static void sound_item(const std::string &name, const std::string &colour);
|
||||
static void sound_item_refresh();
|
||||
static void add_audio_device(const std::string &name);
|
||||
static lo_address m_address;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user