diff --git a/samplebrain/interface/samplebrain.ui b/samplebrain/interface/samplebrain.ui index 42b28f2..2c5adba 100644 --- a/samplebrain/interface/samplebrain.ui +++ b/samplebrain/interface/samplebrain.ui @@ -11,7 +11,7 @@ - samplebrain 0.12 + samplebrain 0.14 @@ -1123,6 +1123,13 @@ + + + + stereo mode + + + @@ -2673,6 +2680,22 @@ + + checkBoxStereo + clicked(bool) + MainWindow + stereo_mode(bool) + + + 539 + 594 + + + 454 + 397 + + + play_slot() @@ -2742,6 +2765,7 @@ autotune(double) load_session() save_session() + stereo_mode(bool) diff --git a/samplebrain/qt/MainWindow.cpp b/samplebrain/qt/MainWindow.cpp index 34de1a6..2801cbc 100644 --- a/samplebrain/qt/MainWindow.cpp +++ b/samplebrain/qt/MainWindow.cpp @@ -49,9 +49,11 @@ void MainWindow::init_from_session(const string &filename) { ifstream ifs(filename.c_str(),ios::binary); brain s,t; - + u32 version=0; + ifs||version; renderer r(s,t); ifs||r; + ifs||r; u32 target_windowsize; u32 source_windowsize; diff --git a/samplebrain/qt/MainWindow.h b/samplebrain/qt/MainWindow.h index 390e2e7..08b275f 100644 --- a/samplebrain/qt/MainWindow.h +++ b/samplebrain/qt/MainWindow.h @@ -266,6 +266,10 @@ private slots: m_feedback.poll(m_Ui.statusbar); } + void stereo_mode(bool s) { + lo_send(m_audio_address,"/stereo","i",s); + } + private: void init_from_session(const string &filename); diff --git a/samplebrain/qt/audio_thread.cpp b/samplebrain/qt/audio_thread.cpp index 7ec7c87..2b68062 100644 --- a/samplebrain/qt/audio_thread.cpp +++ b/samplebrain/qt/audio_thread.cpp @@ -24,11 +24,13 @@ audio_thread::audio_thread(process_thread &p) : m_audio_device(NULL), m_osc("8888"), m_process_thread(p), - m_brain_mutex(p.m_brain_mutex) + m_brain_mutex(p.m_brain_mutex), + m_stereo_mode(false) { start_audio(); pthread_mutex_lock(m_brain_mutex); - m_renderer = new renderer(p.m_source,p.m_target); + m_left_renderer = new renderer(p.m_source,p.m_left_target); + m_right_renderer = new renderer(p.m_source,p.m_right_target); pthread_mutex_unlock(m_brain_mutex); m_osc.run(); } @@ -38,7 +40,8 @@ static bool state = 1; audio_thread::~audio_thread() { state=0; if (m_audio_device!=NULL) delete m_audio_device; - delete m_renderer; + delete m_left_renderer; + delete m_right_renderer; } void audio_thread::start_audio() { @@ -64,80 +67,113 @@ void audio_thread::process(sample &s, sample &s2) { string name = cmd.m_name; //cerr<set_playing(true); + m_left_renderer->set_playing(true); + m_right_renderer->set_playing(true); } if (name=="/pause") { - m_renderer->set_playing(false); + m_left_renderer->set_playing(false); + m_right_renderer->set_playing(false); } if (name=="/ratio") { - m_renderer->get_params()->m_ratio = cmd.get_float(0); + m_left_renderer->get_params()->m_ratio = cmd.get_float(0); + m_right_renderer->get_params()->m_ratio = cmd.get_float(0); } if (name=="/n_ratio") { - m_renderer->get_params()->m_n_ratio = cmd.get_float(0); + m_left_renderer->get_params()->m_n_ratio = cmd.get_float(0); + m_right_renderer->get_params()->m_n_ratio = cmd.get_float(0); } if (name=="/fft1_start") { - m_renderer->get_params()->m_fft1_start = cmd.get_int(0); + m_left_renderer->get_params()->m_fft1_start = cmd.get_int(0); + m_right_renderer->get_params()->m_fft1_start = cmd.get_int(0); } if (name=="/fft1_end") { - m_renderer->get_params()->m_fft1_end = cmd.get_int(0); + m_left_renderer->get_params()->m_fft1_end = cmd.get_int(0); + m_right_renderer->get_params()->m_fft1_end = cmd.get_int(0); } if (name=="/novelty") { - m_renderer->get_params()->m_usage_importance = cmd.get_float(0); + m_left_renderer->get_params()->m_usage_importance = cmd.get_float(0); + m_right_renderer->get_params()->m_usage_importance = cmd.get_float(0); } if (name=="/stickyness") { - m_renderer->get_params()->m_stickyness = cmd.get_float(0); + m_left_renderer->get_params()->m_stickyness = cmd.get_float(0); + m_right_renderer->get_params()->m_stickyness = cmd.get_float(0); } if (name=="/autotune") { - m_renderer->set_autotune(cmd.get_float(0)); + m_left_renderer->set_autotune(cmd.get_float(0)); + m_right_renderer->set_autotune(cmd.get_float(0)); } if (name=="/restart_audio") { start_audio(); } if (name=="/volume") { - m_renderer->set_volume(cmd.get_float(0)*10); + m_left_renderer->set_volume(cmd.get_float(0)*10); + m_right_renderer->set_volume(cmd.get_float(0)*10); } if (name=="/search_algo") { switch(cmd.get_int(0)) { - case 0: m_renderer->set_search_algo(renderer::BASIC); break; - case 1: m_renderer->set_search_algo(renderer::REV_BASIC); break; - case 2: m_renderer->set_search_algo(renderer::SYNAPTIC); break; - case 3: m_renderer->set_search_algo(renderer::SYNAPTIC_SLIDE); break; + case 0: m_left_renderer->set_search_algo(renderer::BASIC); break; + case 1: m_left_renderer->set_search_algo(renderer::REV_BASIC); break; + case 2: m_left_renderer->set_search_algo(renderer::SYNAPTIC); break; + case 3: m_left_renderer->set_search_algo(renderer::SYNAPTIC_SLIDE); break; + } + switch(cmd.get_int(0)) { + case 0: m_right_renderer->set_search_algo(renderer::BASIC); break; + case 1: m_right_renderer->set_search_algo(renderer::REV_BASIC); break; + case 2: m_right_renderer->set_search_algo(renderer::SYNAPTIC); break; + case 3: m_right_renderer->set_search_algo(renderer::SYNAPTIC_SLIDE); break; } } if (name=="/n_mix") { - m_renderer->set_n_mix(cmd.get_float(0)); + m_left_renderer->set_n_mix(cmd.get_float(0)); + m_right_renderer->set_n_mix(cmd.get_float(0)); } if (name=="/target_mix") { - m_renderer->set_target_mix(cmd.get_float(0)); + m_left_renderer->set_target_mix(cmd.get_float(0)); + m_right_renderer->set_target_mix(cmd.get_float(0)); } if (name=="/record") { - m_renderer->set_playing(true); + m_left_renderer->set_playing(true); + m_right_renderer->set_playing(true); m_audio_device->start_recording(cmd.get_string(0)); } if (name=="/stop") { m_audio_device->stop_recording(); - m_renderer->set_playing(false); + m_left_renderer->set_playing(false); + m_right_renderer->set_playing(false); } if (name=="/boredom") { - m_renderer->get_source().set_usage_falloff(cmd.get_float(0)); + m_left_renderer->get_source().set_usage_falloff(cmd.get_float(0)); + m_right_renderer->get_source().set_usage_falloff(cmd.get_float(0)); } if (name=="/synapses") { - m_renderer->get_params()->m_num_synapses=cmd.get_int(0); + m_left_renderer->get_params()->m_num_synapses=cmd.get_int(0); + m_right_renderer->get_params()->m_num_synapses=cmd.get_int(0); } if (name=="/search-stretch") { - m_renderer->set_stretch(cmd.get_int(0)); + m_left_renderer->set_stretch(cmd.get_int(0)); + m_right_renderer->set_stretch(cmd.get_int(0)); } if (name=="/slide-error") { - m_renderer->set_slide_error(cmd.get_int(0)); + m_left_renderer->set_slide_error(cmd.get_int(0)); + m_right_renderer->set_slide_error(cmd.get_int(0)); + } + if (name=="/stereo") { + m_stereo_mode = cmd.get_int(0); + m_left_renderer->reset(); + m_right_renderer->reset(); } } s.zero(); s2.zero(); if (!pthread_mutex_trylock(m_brain_mutex)) { - m_renderer->process(s.get_length(),s.get_non_const_buffer()); + m_left_renderer->process(s.get_length(),s.get_non_const_buffer()); + if (m_stereo_mode) { + m_right_renderer->process(s2.get_length(),s2.get_non_const_buffer()); + } else { + s2=s; + } pthread_mutex_unlock(m_brain_mutex); - s2=s; } else { cerr<<"audio no lock..."< #include #include #include +#include #include #include #include @@ -122,6 +123,7 @@ public: QLabel *label_22; QSlider *sliderTargetMix; QDoubleSpinBox *doubleSpinBoxTargetMix; + QCheckBox *checkBoxStereo; QSpacerItem *verticalSpacer; QVBoxLayout *verticalLayout_2; QLabel *label_3; @@ -772,6 +774,11 @@ public: verticalLayout_6->addLayout(horizontalLayout_9); + checkBoxStereo = new QCheckBox(controlTab); + checkBoxStereo->setObjectName(QString::fromUtf8("checkBoxStereo")); + + verticalLayout_6->addWidget(checkBoxStereo); + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); verticalLayout_6->addItem(verticalSpacer); @@ -1110,6 +1117,7 @@ public: QObject::connect(doubleSpinBoxAutotune, SIGNAL(valueChanged(double)), MainWindow, SLOT(autotune(double))); QObject::connect(pushButtonLoadSession, SIGNAL(released()), MainWindow, SLOT(load_session())); QObject::connect(pushButtonSaveSession, SIGNAL(released()), MainWindow, SLOT(save_session())); + QObject::connect(checkBoxStereo, SIGNAL(clicked(bool)), MainWindow, SLOT(stereo_mode(bool))); tabWidget->setCurrentIndex(0); @@ -1119,7 +1127,7 @@ public: void retranslateUi(QMainWindow *MainWindow) { - MainWindow->setWindowTitle(QApplication::translate("MainWindow", "samplebrain 0.12", 0, QApplication::UnicodeUTF8)); + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "samplebrain 0.14", 0, QApplication::UnicodeUTF8)); label_19->setText(QApplication::translate("MainWindow", "brain tweaks", 0, QApplication::UnicodeUTF8)); label_6->setText(QApplication::translate("MainWindow", "fft / mfcc", 0, QApplication::UnicodeUTF8)); #ifndef QT_NO_TOOLTIP @@ -1236,6 +1244,7 @@ public: #ifndef QT_NO_TOOLTIP sliderTargetMix->setToolTip(QApplication::translate("MainWindow", "mix in the original blocks", 0, QApplication::UnicodeUTF8)); #endif // QT_NO_TOOLTIP + checkBoxStereo->setText(QApplication::translate("MainWindow", "stereo mode", 0, QApplication::UnicodeUTF8)); label_3->setText(QApplication::translate("MainWindow", "brain contents", 0, QApplication::UnicodeUTF8)); pushButtonLoadSound->setText(QApplication::translate("MainWindow", "load sound", 0, QApplication::UnicodeUTF8)); pushButtonDeleteSound->setText(QApplication::translate("MainWindow", "delete selected", 0, QApplication::UnicodeUTF8)); @@ -1273,4 +1282,4 @@ namespace Ui { QT_END_NAMESPACE -#endif // SAMPLEBRAINQ13021_H +#endif // SAMPLEBRAINSM7172_H diff --git a/samplebrain/qt/process_thread.cpp b/samplebrain/qt/process_thread.cpp index 1900a42..0673830 100644 --- a/samplebrain/qt/process_thread.cpp +++ b/samplebrain/qt/process_thread.cpp @@ -59,7 +59,7 @@ void process_thread::process() { //cerr<reset(); + 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_target.clear_sounds(); - m_target.load_sound(cmd.get_string(0)); + 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") { @@ -95,7 +98,8 @@ void process_thread::process() { } if (name=="/generate_target") { pthread_mutex_lock(m_brain_mutex); - m_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); pthread_mutex_unlock(m_brain_mutex); } if (name=="/window_type") { @@ -139,18 +143,23 @@ void process_thread::save_source(const std::string &filename) { pthread_mutex_unlock(m_brain_mutex); } -// remember to change GUI side to match... +// remember to change GUI side to match in MainWindow.cpp void process_thread::load_session(const std::string &filename) { pthread_mutex_lock(m_brain_mutex); m_source.clear(); - m_target.clear(); + m_left_target.clear(); + m_right_target.clear(); ifstream ifs(filename.c_str(),ios::binary); - ifs||(*m_renderer); + u32 version=0; + ifs||version; + ifs||(*m_left_renderer); + ifs||(*m_right_renderer); ifs||m_source_block_size||m_source_overlap; ifs||m_target_block_size||m_target_overlap; ifs||m_window_type||m_target_window_type; ifs||m_source; - ifs||m_target; + ifs||m_left_target; + ifs||m_right_target; ifs.close(); pthread_mutex_unlock(m_brain_mutex); } @@ -158,12 +167,16 @@ void process_thread::load_session(const std::string &filename) { void process_thread::save_session(const std::string &filename) { pthread_mutex_lock(m_brain_mutex); ofstream ofs(filename.c_str(),ios::binary); - ofs||(*m_renderer); + u32 version=0; + ofs||version; + ofs||(*m_left_renderer); + ofs||(*m_right_renderer); ofs||m_source_block_size||m_source_overlap; ofs||m_target_block_size||m_target_overlap; ofs||m_window_type||m_target_window_type; ofs||m_source; - ofs||m_target; + ofs||m_left_target; + ofs||m_right_target; ofs.close(); pthread_mutex_unlock(m_brain_mutex); } diff --git a/samplebrain/qt/process_thread.h b/samplebrain/qt/process_thread.h index 7d87c69..02b7af1 100644 --- a/samplebrain/qt/process_thread.h +++ b/samplebrain/qt/process_thread.h @@ -30,7 +30,10 @@ public: pthread_mutex_t* m_brain_mutex; - void register_renderer(renderer *p) { m_renderer=p; } + void register_renderer(renderer *lr, renderer *rr) { + m_left_renderer=lr; + m_right_renderer=rr; + } void process(); @@ -41,7 +44,7 @@ public: void save_session(const std::string &filename); // only for use in mutex - brain m_source, m_target; + brain m_source, m_left_target, m_right_target; private: OSC_server m_osc; @@ -54,7 +57,8 @@ private: pthread_t *m_thread; // only use in mutex obvs... - renderer *m_renderer; + renderer *m_left_renderer; + renderer *m_right_renderer; }; } diff --git a/samplebrain/qt/qtmain.cpp b/samplebrain/qt/qtmain.cpp index df570ec..01cf308 100644 --- a/samplebrain/qt/qtmain.cpp +++ b/samplebrain/qt/qtmain.cpp @@ -36,7 +36,7 @@ int main( int argc , char *argv[] ){ process_thread pt; audio_thread at(pt); - pt.register_renderer(at.m_renderer); + pt.register_renderer(at.m_left_renderer, at.m_right_renderer); return app.exec(); } diff --git a/samplebrain/src/brain.cpp b/samplebrain/src/brain.cpp index 229518d..f2b6378 100644 --- a/samplebrain/src/brain.cpp +++ b/samplebrain/src/brain.cpp @@ -39,7 +39,7 @@ brain::brain() : // load, chop up and add to brain // todo: add tags -void brain::load_sound(std::string filename) { +void brain::load_sound(std::string filename, stereo_mode mode) { SF_INFO sfinfo; sfinfo.format=0; SNDFILE* f=sf_open(filename.c_str(), SFM_READ, &sfinfo); @@ -47,13 +47,24 @@ void brain::load_sound(std::string filename) { sample s(sfinfo.frames); float *temp = new float[sfinfo.channels * sfinfo.frames]; sf_readf_float(f, temp, sfinfo.channels * sfinfo.frames); - // mix down stereo to mono - for(u32 i=0; i1) si++; + s[i]=temp[si]; } } + delete[] temp; m_samples.push_back(sound(filename,s)); status::update("loaded %s",filename.c_str()); @@ -183,15 +194,15 @@ void brain::build_synapses_thresh(search_params ¶ms, double thresh) { double err = m_average_error*thresh; u32 brain_size = m_blocks.size(); u32 outer_index = 0; - for (auto i:m_blocks) { + for (vector::iterator i=m_blocks.begin(); i!=m_blocks.end(); ++i) { u32 index = 0; status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); - for (auto j:m_blocks) { + for (vector::iterator j=m_blocks.begin(); j!=m_blocks.end(); ++j) { if (index!=outer_index) { // collect connections that are under threshold in closeness - double diff = i.compare(j,params); + double diff = i->compare(*j,params); if (diffget_synapse().push_back(index); } } ++index; @@ -207,16 +218,16 @@ void brain::build_synapses_fixed(search_params ¶ms) { u32 num_synapses = NUM_FIXED_SYNAPSES; if (num_synapses>=m_blocks.size()) num_synapses=m_blocks.size()-1; - for (auto i:m_blocks) { + for (vector::iterator i=m_blocks.begin(); i!=m_blocks.end(); ++i) { status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); u32 index = 0; vector> collect; // collect comparisons to all other blocks - for (auto j:m_blocks) { + for (vector::iterator j=m_blocks.begin(); j!=m_blocks.end(); ++j) { assert(indexcompare(*j,params); collect.push_back(pair(index,diff)); } ++index; @@ -229,11 +240,10 @@ void brain::build_synapses_fixed(search_params ¶ms) { return a.secondget_synapse().push_back(collect[n].first); } ++outer_index; @@ -255,9 +265,10 @@ u32 brain::search_synapses(const block &target, search_params ¶ms) { const block ¤t = get_block(m_current_block_index); double closest = DBL_MAX; u32 closest_index = 0; + // find nearest in synaptic connections if (current.get_synapse_const().size()params.m_num_synapses); @@ -351,8 +362,8 @@ bool brain::unit_test() { assert(b.m_samples.size()==0); assert(b.m_blocks.size()==0); - b.load_sound("test_data/100f32.wav"); - b.load_sound("test_data/100i16.wav"); + b.load_sound("test_data/100f32.wav",MIX); + b.load_sound("test_data/100i16.wav",MIX); assert(b.m_samples.size()==2); b.init(10, 0, window::RECTANGLE); @@ -367,9 +378,9 @@ bool brain::unit_test() { // replicate brains brain b2; - b2.load_sound("test_data/up.wav"); + b2.load_sound("test_data/up.wav",MIX); brain b3; - b3.load_sound("test_data/up.wav"); + b3.load_sound("test_data/up.wav",MIX); b2.init(512, 0, window::BLACKMAN); b3.init(512, 0, window::BLACKMAN); diff --git a/samplebrain/src/brain.h b/samplebrain/src/brain.h index 52a442d..1866dab 100644 --- a/samplebrain/src/brain.h +++ b/samplebrain/src/brain.h @@ -32,6 +32,8 @@ class brain { public: brain(); + enum stereo_mode { MIX, LEFT, RIGHT }; + // rewrites whole brain void init(u32 block_size, u32 overlap, window::type t, bool ditchpcm=false); @@ -53,7 +55,7 @@ public: // load, chop up and add to brain // todo: add tags - void load_sound(std::string filename); + void load_sound(std::string filename, stereo_mode mode); void delete_sound(std::string filename); void clear_sounds() { m_samples.clear(); } // take another brain and rebuild this brain from bits of that one diff --git a/samplebrain/src/renderer.cpp b/samplebrain/src/renderer.cpp index 5170915..ad56b40 100644 --- a/samplebrain/src/renderer.cpp +++ b/samplebrain/src/renderer.cpp @@ -258,11 +258,11 @@ ios &spiralcore::operator||(ios &s, renderer &r) { bool renderer::unit_test() { brain source; - source.load_sound("test_data/up.wav"); + source.load_sound("test_data/up.wav", brain::MIX); source.init(10,0,window::RECTANGLE); brain target; - target.load_sound("test_data/up.wav"); + target.load_sound("test_data/up.wav", brain::MIX); target.init(10,0,window::RECTANGLE); renderer rr(source,target); diff --git a/samplebrain/src/renderer.h b/samplebrain/src/renderer.h index bfe2dff..767cfd1 100644 --- a/samplebrain/src/renderer.h +++ b/samplebrain/src/renderer.h @@ -27,9 +27,9 @@ namespace spiralcore { public: renderer(brain &source, brain &target) : m_source(source), - m_target(target), - m_search_params(0,0,0,100,0) - { init(source,target); } + m_target(target), + m_search_params(0,0,0,100,0) + { init(source,target); } enum search_algo { BASIC = 0,