stereo mode

This commit is contained in:
dave griffiths 2016-02-03 15:45:09 +00:00
parent e966d6b3af
commit 7f0b469709
13 changed files with 183 additions and 77 deletions

View File

@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>samplebrain 0.12</string>
<string>samplebrain 0.14</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_4">
@ -1123,6 +1123,13 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxStereo">
<property name="text">
<string>stereo mode</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@ -2673,6 +2680,22 @@
</hint>
</hints>
</connection>
<connection>
<sender>checkBoxStereo</sender>
<signal>clicked(bool)</signal>
<receiver>MainWindow</receiver>
<slot>stereo_mode(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>539</x>
<y>594</y>
</hint>
<hint type="destinationlabel">
<x>454</x>
<y>397</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>play_slot()</slot>
@ -2742,6 +2765,7 @@
<slot>autotune(double)</slot>
<slot>load_session()</slot>
<slot>save_session()</slot>
<slot>stereo_mode(bool)</slot>
</slots>
<buttongroups>
<buttongroup name="buttonGroup_2"/>

View File

@ -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;

View File

@ -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);

View File

@ -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<<name<<endl;
if (name=="/start") {
m_renderer->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..."<<endl;
}

View File

@ -33,7 +33,8 @@ public:
static void run_audio(void* c, unsigned int frames);
audio_device *m_audio_device;
renderer *m_renderer;
renderer *m_left_renderer;
renderer *m_right_renderer;
private:
void start_audio();
@ -41,7 +42,7 @@ private:
OSC_server m_osc;
process_thread &m_process_thread;
pthread_mutex_t* m_brain_mutex;
bool m_stereo_mode;
};
}

View File

@ -1,18 +1,19 @@
/********************************************************************************
** Form generated from reading UI file 'samplebrainQ13021.ui'
** Form generated from reading UI file 'samplebrainSm7172.ui'
**
** Created by: Qt User Interface Compiler version 4.8.6
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef SAMPLEBRAINQ13021_H
#define SAMPLEBRAINQ13021_H
#ifndef SAMPLEBRAINSM7172_H
#define SAMPLEBRAINSM7172_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QCheckBox>
#include <QtGui/QDial>
#include <QtGui/QDoubleSpinBox>
#include <QtGui/QGridLayout>
@ -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

View File

@ -59,7 +59,7 @@ void process_thread::process() {
//cerr<<name<<endl;
if (name=="/load_sample") {
pthread_mutex_lock(m_brain_mutex);
m_source.load_sound(cmd.get_string(0));
m_source.load_sound(cmd.get_string(0),brain::MIX);
pthread_mutex_unlock(m_brain_mutex);
}
if (name=="/delete_sample") {
@ -78,13 +78,16 @@ void process_thread::process() {
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_renderer->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);
}

View File

@ -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;
};
}

View File

@ -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();
}

View File

@ -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; i<sfinfo.frames; i++) {
s[i]=0;
for(u32 j = 0; j < sfinfo.channels; j++) {
s[i]+=temp[i*sfinfo.channels + j];
if (mode==MIX) {
for(u32 i=0; i<sfinfo.frames; i++) {
s[i]=0;
// mix down stereo to mono
for(u32 j = 0; j < sfinfo.channels; j++) {
s[i]+=temp[i*sfinfo.channels + j];
}
}
} else {
// just take one channel (assume stereo, split if mono)
for(u32 i=0; i<sfinfo.frames; i++) {
u32 si=i*sfinfo.channels;
if (mode==RIGHT && sfinfo.channels>1) 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 &params, 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<block>::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<block>::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 (diff<err) {
i.get_synapse().push_back(index);
i->get_synapse().push_back(index);
}
}
++index;
@ -207,16 +218,16 @@ void brain::build_synapses_fixed(search_params &params) {
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<block>::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<pair<u32,double>> collect;
// collect comparisons to all other blocks
for (auto j:m_blocks) {
for (vector<block>::iterator j=m_blocks.begin(); j!=m_blocks.end(); ++j) {
assert(index<m_blocks.size());
if (index!=outer_index) {
double diff = i.compare(j,params);
double diff = i->compare(*j,params);
collect.push_back(pair<u32,double>(index,diff));
}
++index;
@ -229,11 +240,10 @@ void brain::build_synapses_fixed(search_params &params) {
return a.second<b.second;
});
// add the closest ones to the list
for(u32 n=0; n<num_synapses; ++n) {
assert(collect[n].first<m_blocks.size());
i.get_synapse().push_back(collect[n].first);
i->get_synapse().push_back(collect[n].first);
}
++outer_index;
@ -255,9 +265,10 @@ u32 brain::search_synapses(const block &target, search_params &params) {
const block &current = 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) {
params.m_num_synapses = current.get_synapse_const().size()-1;
params.m_num_synapses = current.get_synapse_const().size()-1;
}
// assert(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);

View File

@ -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

View File

@ -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);

View File

@ -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,