Compare commits

..

No commits in common. "production" and "0.18.4_release" have entirely different histories.

24 changed files with 479 additions and 782 deletions

View File

@ -41,16 +41,12 @@ written to run on a couple of computers!) you will have to bear with
us as we gradually stabilise things based on your feedback. There us as we gradually stabilise things based on your feedback. There
might currently be problems running it on 64bit Windows. might currently be problems running it on 64bit Windows.
* **Windows**: [samplebrain_0.18.5_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.5_win.zip) * **Windows**: [samplebrain_0.18.4_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_win.zip)
* **Mac (intel/m1)**: [samplebrain_0.18.5_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.5_macintel.app.zip) * **Mac (intel/m1)**: [samplebrain_0.18.4_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_macintel.app.zip)
Changes in 0.18.5 (relased 28/10/22): Changes in 0.18.4: New audio device settings window and updated
windows build. Better default block size, tool tip tweaks and fixes
* Target sound filename shown (and tells you if you don't have one) for dark themes by [Claude Heiland-Allen](https://mathr.co.uk/).
* More soundfile formats supported (aiff,aifc,au,snd,fasttracker xi,flac)
* New configurable OSC ports in settings
* Warning boxes if the OSC network connection fails
* File path memory per-dialog rather than global
For old versions see the [changelog](changelog.md) For old versions see the [changelog](changelog.md)

View File

@ -27,16 +27,9 @@
using namespace std; using namespace std;
MainWindow::MainWindow(const string &port, const string &audio_port, const string &process_port, QSettings *settings) : MainWindow::MainWindow() :
m_last_sound_file("."), m_last_file("."),
m_last_target_file("."), m_feedback("8890")
m_last_brain_file("."),
m_last_session_file("."),
m_last_recording_file("."),
m_feedback(port),
m_audio_port(audio_port),
m_process_port(process_port),
m_format_string("Microsoft WAV (*.wav);;SGI/Apple AIFF (*.aiff);;SGI/Apple AIFC (*.aifc);;Sun/DEC/NeXT AU (*.au);;Sun/DEC/NeXT SND (*.snd);;Fasttracker 2 XI (*.xi);;Free Lossless Audio Codec FLAC (*.flac);;All files (*.*)")
{ {
m_sound_item_enable_mapper = new QSignalMapper(this); m_sound_item_enable_mapper = new QSignalMapper(this);
m_sound_item_delete_mapper = new QSignalMapper(this); m_sound_item_delete_mapper = new QSignalMapper(this);
@ -56,7 +49,7 @@ MainWindow::MainWindow(const string &port, const string &audio_port, const strin
m_Ui.brain_contents->setSpacing(0); m_Ui.brain_contents->setSpacing(0);
m_Ui.brain_contents->setContentsMargins(0,0,0,0); m_Ui.brain_contents->setContentsMargins(0,0,0,0);
m_settings_dialog = new SettingsDialog(this,settings); m_settings_dialog = new SettingsDialog(this);
// add default local dest // add default local dest
// turn on first one // turn on first one
@ -66,8 +59,8 @@ MainWindow::MainWindow(const string &port, const string &audio_port, const strin
for (int i=0; i<10; i++) { for (int i=0; i<10; i++) {
osc_destination d; osc_destination d;
d.m_id=i; d.m_id=i;
d.m_audio_address = lo_address_new_from_url(string("osc.udp://localhost:"+m_audio_port).c_str()); d.m_audio_address = lo_address_new_from_url("osc.udp://localhost:8888");
d.m_process_address = lo_address_new_from_url(string("osc.udp://localhost:"+m_process_port).c_str()); d.m_process_address = lo_address_new_from_url("osc.udp://localhost:8889");
if (i==0) d.m_enabled=true; if (i==0) d.m_enabled=true;
else d.m_enabled=false; else d.m_enabled=false;
add_gui_address(d,enable_mapper); add_gui_address(d,enable_mapper);
@ -161,12 +154,6 @@ void MainWindow::init_from_session(const string &filename) {
m_Ui.spinBoxSlideError->setValue(r.get_slide_error()); m_Ui.spinBoxSlideError->setValue(r.get_slide_error());
// target // target
if (t.get_samples().size()>0) {
// extract target filename from brain sample
string fn = t.get_samples().begin()->m_filename;
m_Ui.labelTargetSound->setText("loaded: "+QFileInfo(QString::fromStdString(fn)).fileName());
}
m_Ui.spinBoxBlockSizeTarget->setValue(t.get_block_size()); m_Ui.spinBoxBlockSizeTarget->setValue(t.get_block_size());
m_Ui.doubleSpinBoxBlockOverlapTarget->setValue(t.get_overlap()/(float)t.get_block_size()); m_Ui.doubleSpinBoxBlockOverlapTarget->setValue(t.get_overlap()/(float)t.get_block_size());

View File

@ -18,7 +18,6 @@
#include <QDirIterator> #include <QDirIterator>
#include <QFileDialog> #include <QFileDialog>
#include <QLineEdit> #include <QLineEdit>
#include <QMessageBox>
#include "ui_samplebrain.h" #include "ui_samplebrain.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
@ -33,22 +32,12 @@
using namespace std; using namespace std;
using namespace spiralcore; using namespace spiralcore;
class QSettings;
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
MainWindow(const string &port, const string &audio_port, const string &process_port, QSettings *settings); MainWindow();
void message(const string &msg) {
QMessageBox::information(this,"problem",msg.c_str(), QMessageBox::Ok);
}
bool ok() {
return m_feedback.ok();
}
// all this to work around liblo's use of varargs... // all this to work around liblo's use of varargs...
void send_audio_osc(const char *name, const char *types) { void send_audio_osc(const char *name, const char *types) {
@ -206,15 +195,13 @@ private slots:
void run_slot() {} void run_slot() {}
void load_target() { void load_target() {
QString path=QFileDialog::getOpenFileName(this, m_last_file=QFileDialog::getOpenFileName(
QString("Select an audio file"), this,
m_last_target_file, QString("Select an wav file"),
m_format_string); m_last_file,
if (m_last_target_file!="") { QString("Sounds (*.wav)"));
m_last_target_file=path;
m_Ui.labelTargetSound->setText("loaded: "+QFileInfo(path).fileName()); send_process_osc("/load_target","s",m_last_file.toStdString().c_str());
send_process_osc("/load_target","s",m_last_target_file.toStdString().c_str());
}
} }
void target_block_size(int s) { send_process_osc("/target_block_size","i",s); } void target_block_size(int s) { send_process_osc("/target_block_size","i",s); }
void target_block_overlap(double s) { send_process_osc("/target_overlap","f",s); } void target_block_overlap(double s) { send_process_osc("/target_overlap","f",s); }
@ -224,31 +211,30 @@ private slots:
void fft_spectrum_size(int) {} void fft_spectrum_size(int) {}
void generate() { send_process_osc("/generate_brain",""); } void generate() { send_process_osc("/generate_brain",""); }
void load_sound() { void load_sound() {
QString path=QFileDialog::getOpenFileName(this, m_last_file=QFileDialog::getOpenFileName(
this,
QString("Select a wav file"), QString("Select a wav file"),
m_last_sound_file, m_last_file,
m_format_string); QString("Sounds (*.wav)"));
send_process_osc("/load_sample","s",m_last_file.toStdString().c_str());
sound_items::sound_item &si = m_sound_items.add(m_Ui.brain_contents, m_last_file.toStdString(),true);
if (path!="") {
m_last_sound_file=path;
send_process_osc("/load_sample","s",m_last_sound_file.toStdString().c_str());
sound_items::sound_item &si = m_sound_items.add(m_Ui.brain_contents, m_last_sound_file.toStdString(),true);
QObject::connect(si.m_enable, SIGNAL(clicked()), m_sound_item_enable_mapper, SLOT(map())); QObject::connect(si.m_enable, SIGNAL(clicked()), m_sound_item_enable_mapper, SLOT(map()));
m_sound_item_enable_mapper->setMapping(si.m_enable, si.m_id); m_sound_item_enable_mapper->setMapping(si.m_enable, si.m_id);
QObject::connect(si.m_del, SIGNAL(clicked()), m_sound_item_delete_mapper, SLOT(map())); QObject::connect(si.m_del, SIGNAL(clicked()), m_sound_item_delete_mapper, SLOT(map()));
m_sound_item_delete_mapper->setMapping(si.m_del, si.m_id); m_sound_item_delete_mapper->setMapping(si.m_del, si.m_id);
} }
}
void load_sounds() { void load_sounds() {
QString path=QFileDialog::getExistingDirectory(this, m_last_file=QFileDialog::getExistingDirectory(this,
QString("Select a directory of wav files"), QString("Select a directory"),
m_last_directory_file); m_last_file);
if (path!="") {
m_last_directory_file=path; QDirIterator dirIt(m_last_file,QDirIterator::Subdirectories);
QDirIterator dirIt(m_last_directory_file,QDirIterator::Subdirectories);
while (dirIt.hasNext()) { while (dirIt.hasNext()) {
dirIt.next(); dirIt.next();
if (QFileInfo(dirIt.filePath()).isFile() && if (QFileInfo(dirIt.filePath()).isFile() &&
@ -265,7 +251,6 @@ private slots:
} }
} }
} }
}
void select_all() { void select_all() {
for (auto &si:m_sound_items.m_sound_items) { for (auto &si:m_sound_items.m_sound_items) {
@ -319,11 +304,12 @@ private slots:
void record() { void record() {
if (m_save_wav=="") { if (m_save_wav=="") {
m_last_recording_file=QFileDialog::getSaveFileName(this, m_last_file=QFileDialog::getSaveFileName(
this,
QString("Select a wav file"), QString("Select a wav file"),
m_last_recording_file, m_last_file,
QString("Sounds (*.wav);;All files (*.*)")); QString("Sounds (*.wav)"));
m_save_wav = m_last_recording_file.toStdString(); m_save_wav = m_last_file.toStdString();
// chop off .wav // chop off .wav
size_t pos = m_save_wav.find_last_of("."); size_t pos = m_save_wav.find_last_of(".");
if (pos!=string::npos) { if (pos!=string::npos) {
@ -344,48 +330,43 @@ private slots:
} }
void load_brain() { void load_brain() {
QString path=QFileDialog::getOpenFileName(this, m_last_file=QFileDialog::getOpenFileName(
this,
QString("Select a brain file"), QString("Select a brain file"),
m_last_brain_file, m_last_file,
QString("Brains (*.brain);;All files (*.*)")); QString("Brains (*.brain)"));
if (path!="") { send_process_osc("/load_brain","s",m_last_file.toStdString().c_str());
m_last_brain_file=path;
send_process_osc("/load_brain","s",m_last_brain_file.toStdString().c_str());
}
} }
void save_brain() { void save_brain() {
QString path=QFileDialog::getSaveFileName(this, m_last_file=QFileDialog::getSaveFileName(
this,
QString("Select a brain file"), QString("Select a brain file"),
m_last_brain_file, m_last_file,
QString("Brains (*.brain);;All files (*.*)")); QString("Brains (*.brain)"));
if (path!="") {
m_last_brain_file=path; send_process_osc("/save_brain","s",m_last_file.toStdString().c_str());
send_process_osc("/save_brain","s",m_last_brain_file.toStdString().c_str());
}
} }
void load_session() { void load_session() {
QString path=QFileDialog::getOpenFileName(this, m_last_file=QFileDialog::getOpenFileName(
this,
QString("Select a session file"), QString("Select a session file"),
m_last_session_file, m_last_file,
QString("Sessions *.samplebrain (*.samplebrain);;All files (*.*)")); QString("Sessions *.samplebrain (*.samplebrain)"));
if (path!="") {
m_last_session_file=path; send_process_osc("/load_session","s",m_last_file.toStdString().c_str());
send_process_osc("/load_session","s",m_last_session_file.toStdString().c_str()); init_from_session(m_last_file.toStdString());
init_from_session(m_last_session_file.toStdString());
}
} }
void save_session() { void save_session() {
QString path=QFileDialog::getSaveFileName(this, m_last_file=QFileDialog::getSaveFileName(
this,
QString("Select a session file"), QString("Select a session file"),
m_last_session_file, m_last_file,
QString("Sessions *.samplebrain (*.samplebrain)")); QString("Sessions *.samplebrain (*.samplebrain)"));
if (path!="") {
m_last_session_file=path; send_process_osc("/save_session","s",m_last_file.toStdString().c_str());
send_process_osc("/save_session","s",m_last_session_file.toStdString().c_str());
}
} }
void update_status() { void update_status() {
@ -404,8 +385,8 @@ private slots:
string url = d.m_address->text().toUtf8().constData(); string url = d.m_address->text().toUtf8().constData();
lo_address_free(d.m_audio_address); lo_address_free(d.m_audio_address);
lo_address_free(d.m_process_address); lo_address_free(d.m_process_address);
d.m_audio_address = lo_address_new_from_url(string(url+":"+m_audio_port).c_str()); d.m_audio_address = lo_address_new_from_url(string(url+":8888").c_str());
d.m_process_address = lo_address_new_from_url(string(url+":"+m_process_port).c_str()); d.m_process_address = lo_address_new_from_url(string(url+":8889").c_str());
// start sending messages here // start sending messages here
d.m_enabled=true; d.m_enabled=true;
} else { } else {
@ -450,12 +431,7 @@ private:
QSignalMapper* enable_mapper); QSignalMapper* enable_mapper);
string m_save_wav; string m_save_wav;
QString m_last_sound_file; QString m_last_file;
QString m_last_target_file;
QString m_last_directory_file;
QString m_last_brain_file;
QString m_last_session_file;
QString m_last_recording_file;
unsigned int m_record_id; unsigned int m_record_id;
Ui_MainWindow m_Ui; Ui_MainWindow m_Ui;
feedback m_feedback; feedback m_feedback;
@ -466,7 +442,4 @@ private:
SettingsDialog *m_settings_dialog; SettingsDialog *m_settings_dialog;
audio_thread *m_audio_thread; audio_thread *m_audio_thread;
string m_audio_port;
string m_process_port;
QString m_format_string;
}; };

View File

@ -24,16 +24,12 @@
using namespace std; using namespace std;
SettingsDialog::SettingsDialog(MainWindow *parent, QSettings *settings): SettingsDialog::SettingsDialog(MainWindow *parent):
m_device(""), m_device(""),
m_parent(parent), m_parent(parent),
m_buffersize(2048), m_buffersize(2048),
m_samplerate(44100), m_samplerate(44100) {
m_settings(settings) {
m_Ui.setupUi(this); m_Ui.setupUi(this);
m_Ui.guiOSCLineEdit->setText(settings->value("gui_port").toByteArray().constData());
m_Ui.processOSCLineEdit->setText(settings->value("process_port").toByteArray().constData());
m_Ui.audioOSCLineEdit->setText(settings->value("audio_port").toByteArray().constData());
} }
void SettingsDialog::connect() { void SettingsDialog::connect() {

View File

@ -20,7 +20,6 @@
#include <QtGui> #include <QtGui>
#include <QDialog> #include <QDialog>
#include <QLineEdit> #include <QLineEdit>
#include <QSettings>
#include "ui_settings.h" #include "ui_settings.h"
#include <iostream> #include <iostream>
@ -37,7 +36,7 @@ class SettingsDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
SettingsDialog(MainWindow *parent, QSettings *settings); SettingsDialog(MainWindow *parent);
Ui_SettingsDialog m_Ui; Ui_SettingsDialog m_Ui;
string m_device; string m_device;
@ -63,18 +62,6 @@ class SettingsDialog : public QDialog
void reject() { hide(); } void reject() { hide(); }
void apply() { connect(); } void apply() { connect(); }
void gui_port(QString str) {
m_settings->setValue("gui_port",str);
}
void process_port(QString str) {
m_settings->setValue("process_port",str);
}
void audio_port(QString str) {
m_settings->setValue("audio_port",str);
}
private: private:
void connect(); void connect();
@ -83,7 +70,6 @@ class SettingsDialog : public QDialog
unsigned int m_buffersize; unsigned int m_buffersize;
unsigned int m_samplerate; unsigned int m_samplerate;
QSettings *m_settings;
}; };
#endif #endif

View File

@ -20,23 +20,26 @@
using namespace spiralcore; using namespace spiralcore;
using namespace std; using namespace std;
audio_thread::audio_thread(const string &port, process_thread &p) : audio_thread::audio_thread(process_thread &p) :
m_audio_device(NULL), m_audio_device(NULL),
m_osc(port), m_osc("8888"),
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_bufsize(2048),
m_samplerate(44100), m_samplerate(44100),
m_device("") { m_device("")
{
// start_audio();
pthread_mutex_lock(m_brain_mutex); pthread_mutex_lock(m_brain_mutex);
m_left_renderer = new renderer(p.m_source,p.m_left_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); m_right_renderer = new renderer(p.m_source,p.m_right_target);
m_block_stream = new block_stream(); m_block_stream = new block_stream();
pthread_mutex_unlock(m_brain_mutex); pthread_mutex_unlock(m_brain_mutex);
m_osc.run(); m_osc.run();
// it this threadsafe?
// m_audio_device->report_devices();
} }
static bool state = 1; static bool state = 1;

View File

@ -26,12 +26,12 @@ namespace spiralcore {
class audio_thread { class audio_thread {
public: public:
audio_thread(const string &port, process_thread &p); audio_thread(process_thread &p);
~audio_thread(); ~audio_thread();
void start_audio(); void start_audio();
void restart_audio(const string device, unsigned int samplerate, unsigned int bufsize); void restart_audio(const string device, unsigned int samplerate, unsigned int bufsize);
bool ok() { return m_osc.ok(); }
void process(sample &left_in, sample &right_in, sample &left_out, sample &right_out); void process(sample &left_in, sample &right_in, sample &left_out, sample &right_out);
static void run_audio(void* c, unsigned int frames); static void run_audio(void* c, unsigned int frames);

View File

@ -29,7 +29,6 @@ class feedback {
public: public:
feedback(std::string address); feedback(std::string address);
void poll(QStatusBar *s, sound_items *sound_items, SettingsDialog *settings); void poll(QStatusBar *s, sound_items *sound_items, SettingsDialog *settings);
bool ok() { return m_osc.ok(); }
private: private:

View File

@ -32,8 +32,8 @@ static void* _process(void *c) {
return NULL; return NULL;
} }
process_thread::process_thread(const string &port) : process_thread::process_thread() :
m_osc(port), m_osc("8889"),
m_source_block_size(1000), m_source_block_size(1000),
m_source_overlap(0.75), m_source_overlap(0.75),
m_target_block_size(1000), m_target_block_size(1000),

View File

@ -25,9 +25,9 @@
namespace spiralcore { namespace spiralcore {
class process_thread { class process_thread {
public: public:
process_thread(const string &port); process_thread();
~process_thread(); ~process_thread();
pthread_mutex_t* m_brain_mutex; pthread_mutex_t* m_brain_mutex;
@ -47,13 +47,10 @@ namespace spiralcore {
void load_session(const std::string &filename); void load_session(const std::string &filename);
void save_session(const std::string &filename); void save_session(const std::string &filename);
bool ok() { return m_osc.ok(); }
// only for use in mutex // only for use in mutex
brain m_source, m_left_target, m_right_target; brain m_source, m_left_target, m_right_target;
private: private:
OSC_server m_osc; OSC_server m_osc;
u32 m_source_block_size; u32 m_source_block_size;
float m_source_overlap; float m_source_overlap;
@ -67,6 +64,6 @@ namespace spiralcore {
renderer *m_left_renderer; renderer *m_left_renderer;
renderer *m_right_renderer; renderer *m_right_renderer;
block_stream *m_block_stream; block_stream *m_block_stream;
}; };
} }

View File

@ -19,54 +19,22 @@
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
#include <QtGui> #include <QtGui>
#include <QSettings>
#include "MainWindow.h" #include "MainWindow.h"
#include "process_thread.h" #include "process_thread.h"
#include "audio_thread.h" #include "audio_thread.h"
#include "status.h"
using namespace std; using namespace std;
int main( int argc , char *argv[] ){ int main( int argc , char *argv[] ){
QApplication app(argc, argv); QApplication app(argc, argv);
MainWindow mainWin;
QSettings settings("thentrythis", "samplebrain");
// slight over-use of OSC servers here, but the are packaged nicely for
// threadsafe (nonblocking) communication, and it's useful to expose all
// moving parts for external control (i.e. the processing and the audio)
if (!settings.contains("gui_port")) settings.setValue("gui_port", "62345");
if (!settings.contains("audio_port")) settings.setValue("audio_port", "62346");
if (!settings.contains("process_port")) settings.setValue("process_port", "62347");
string gui_port = settings.value("gui_port").toByteArray().constData();
string audio_port = settings.value("audio_port").toByteArray().constData();
string process_port = settings.value("process_port").toByteArray().constData();
status::set_port(gui_port);
MainWindow mainWin(gui_port,audio_port,process_port,&settings);
mainWin.show(); mainWin.show();
process_thread pt(process_port); process_thread pt;
audio_thread at(audio_port,pt); audio_thread at(pt);
pt.register_renderer(at.m_left_renderer, at.m_right_renderer, at.m_block_stream); pt.register_renderer(at.m_left_renderer, at.m_right_renderer, at.m_block_stream);
mainWin.set_audio_thread(&at);
if (!at.ok()) { mainWin.set_audio_thread(&at);
mainWin.message("problem starting audio thread on port "+audio_port);
}
if (!pt.ok()) {
mainWin.message("problem starting process thread on port "+process_port);
}
if (!mainWin.ok()) {
mainWin.message("problem starting gui thread on port "+gui_port);
}
return app.exec(); return app.exec();
} }

View File

@ -112,7 +112,6 @@ void block::process(const sample &pcm, sample &fft, sample &mfcc, float &freq) {
// calculate fft // calculate fft
std::vector<std::complex<double> > mfspec; std::vector<std::complex<double> > mfspec;
mfspec.reserve(m_block_size);
for (u32 i=0; i<m_block_size; ++i) { for (u32 i=0; i<m_block_size; ++i) {
mfspec.push_back(std::complex<double>(m_fftw->m_spectrum[i][0], mfspec.push_back(std::complex<double>(m_fftw->m_spectrum[i][0],
m_fftw->m_spectrum[i][1])); m_fftw->m_spectrum[i][1]));

View File

@ -79,7 +79,6 @@ void block_stream::init(u32 block_size, u32 overlap, window::type t, bool ditchp
m_window.set_current_type(t); m_window.set_current_type(t);
m_blocks.clear(); m_blocks.clear();
m_blocks.reserve(MAX_BLOCKS);
sample dummy(block_size); sample dummy(block_size);
for (u32 i=0; i<MAX_BLOCKS; i++) { for (u32 i=0; i<MAX_BLOCKS; i++) {
m_blocks.push_back(block(0,"dummy",dummy,44100,m_window)); m_blocks.push_back(block(0,"dummy",dummy,44100,m_window));

View File

@ -69,8 +69,6 @@ void brain::load_sound(std::string filename, stereo_mode mode) {
delete[] temp; delete[] temp;
m_samples.push_back(sound(filename,s)); m_samples.push_back(sound(filename,s));
status::update("loaded %s",filename.c_str()); status::update("loaded %s",filename.c_str());
} else {
status::update("problem loading %s",filename.c_str());
} }
} }
@ -228,7 +226,6 @@ u32 brain::rev_search(const block &target, const search_params &params) {
return furthest_index; return furthest_index;
} }
/*
// really slow - every to every comparison of blocks calculating average distance // really slow - every to every comparison of blocks calculating average distance
double brain::calc_average_diff(search_params &params) { double brain::calc_average_diff(search_params &params) {
double diff=0; double diff=0;
@ -262,7 +259,6 @@ void brain::build_synapses_thresh(search_params &params, double thresh) {
++outer_index; ++outer_index;
} }
} }
*/
void brain::build_synapses_fixed(search_params &params) { void brain::build_synapses_fixed(search_params &params) {
//m_average_error = calc_average_diff(params)*thresh; //m_average_error = calc_average_diff(params)*thresh;

View File

@ -62,8 +62,8 @@ public:
u32 rev_search(const block &target, const search_params &params); u32 rev_search(const block &target, const search_params &params);
// synaptic search // synaptic search
// double calc_average_diff(search_params &params); double calc_average_diff(search_params &params);
// void build_synapses_thresh(search_params &params, double threshold); void build_synapses_thresh(search_params &params, double threshold);
void build_synapses_fixed(search_params &params); void build_synapses_fixed(search_params &params);
u32 search_synapses(const block &target, search_params &params); u32 search_synapses(const block &target, search_params &params);
double get_current_error() { return m_current_error; } double get_current_error() { return m_current_error; }

View File

@ -31,41 +31,41 @@ extern "C" {
#endif #endif
OSC_server::OSC_server(const string &port) : OSC_server::OSC_server(const string &port) :
m_port(port), m_port(port),
m_exit(false), m_exit(false),
m_command_ring_buffer(262144) { m_command_ring_buffer(262144)
cerr<<"OSC using port: ["<<port<<"]"<<endl; {
//cerr<<"using port: ["<<port<<"]"<<endl;
m_server = lo_server_thread_new(port.c_str(), error_handler); m_server = lo_server_thread_new(port.c_str(), error_handler);
if (m_server) {
lo_server_thread_add_method(m_server, NULL, NULL, default_handler, this); lo_server_thread_add_method(m_server, NULL, NULL, default_handler, this);
} else {
cerr<<"error opening OSC port"<<endl;
}
} }
OSC_server::~OSC_server() { OSC_server::~OSC_server()
{
m_exit=true; m_exit=true;
lo_server_thread_stop(m_server); lo_server_thread_stop(m_server);
} }
void OSC_server::run() { void OSC_server::run()
if (!m_server) return; {
lo_server_thread_start(m_server); lo_server_thread_start(m_server);
// while (!m_exit) usleep(1000); // while (!m_exit) usleep(1000);
} }
void OSC_server::error_handler(int num, const char *msg, const char *path) { void OSC_server::error_handler(int num, const char *msg, const char *path)
{
//cerr<<"liblo server error "<<num<<" in path "<<path<<": "<<msg<<endl; //cerr<<"liblo server error "<<num<<" in path "<<path<<": "<<msg<<endl;
cerr<<"liblo server error "<<num<<endl; cerr<<"liblo server error "<<num<<endl;
} }
int OSC_server::default_handler(const char *path, const char *types, lo_arg **argv, int OSC_server::default_handler(const char *path, const char *types, lo_arg **argv,
int argc, lo_message data, void *user_data) { int argc, void *data, void *user_data)
{
OSC_server *server = (OSC_server*)user_data; OSC_server *server = (OSC_server*)user_data;
if (!server) return -1;
unsigned int size = 0; unsigned int size = 0;
for (int i=0; i<argc; i++) { for (int i=0; i<argc; i++)
{
size+=lo_arg_size((lo_type)types[i],argv[i]); size+=lo_arg_size((lo_type)types[i],argv[i]);
// add one for the null terminator // add one for the null terminator
if (types[i]=='s') size++; if (types[i]=='s') size++;
@ -73,10 +73,14 @@ int OSC_server::default_handler(const char *path, const char *types, lo_arg **ar
char *newdata=new char[size]; char *newdata=new char[size];
unsigned int pos=0; unsigned int pos=0;
for (int i=0; i<argc; i++) { for (int i=0; i<argc; i++)
switch (types[i]) { {
case LO_INT32: { switch (types[i])
if (pos+4>COMMAND_DATA_SIZE) { {
case LO_INT32:
{
if (pos+4>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl; cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata; delete[] newdata;
return 1; return 1;
@ -86,8 +90,10 @@ int OSC_server::default_handler(const char *path, const char *types, lo_arg **ar
pos+=4; pos+=4;
} }
break; break;
case LO_FLOAT: { case LO_FLOAT:
if (pos+4>COMMAND_DATA_SIZE) { {
if (pos+4>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl; cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata; delete[] newdata;
return 1; return 1;
@ -97,10 +103,12 @@ int OSC_server::default_handler(const char *path, const char *types, lo_arg **ar
pos+=4; pos+=4;
} }
break; break;
case LO_STRING: { case LO_STRING:
{
int size=strlen(&argv[i]->s); int size=strlen(&argv[i]->s);
if (pos+size+1>COMMAND_DATA_SIZE) { if (pos+size+1>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl; cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata; delete[] newdata;
return 1; return 1;
@ -111,7 +119,8 @@ int OSC_server::default_handler(const char *path, const char *types, lo_arg **ar
pos+=size+1; pos+=size+1;
} }
break; break;
default: { default:
{
cerr<<"unsupported type: "<<types[i]<<endl; cerr<<"unsupported type: "<<types[i]<<endl;
delete[] newdata; delete[] newdata;
return 1; return 1;
@ -120,14 +129,16 @@ int OSC_server::default_handler(const char *path, const char *types, lo_arg **ar
} }
} }
if (1) { //pos==size) hmm if (1)//pos==size) hmm
{
command_ring_buffer::command command(path,types,newdata,pos); command_ring_buffer::command command(path,types,newdata,pos);
if (!server->m_command_ring_buffer.send(command)) { if (!server->m_command_ring_buffer.send(command))
{
//cerr<<"OSC_server - ringbuffer full!"<<endl; //cerr<<"OSC_server - ringbuffer full!"<<endl;
} }
} }
else { else
{
cerr<<"OSC_server::default_handler: size mismatch ["<<pos<<":"<<size<<"], not sending message"<<endl; cerr<<"OSC_server::default_handler: size mismatch ["<<pos<<":"<<size<<"], not sending message"<<endl;
} }

View File

@ -29,10 +29,9 @@ public:
void run(); void run();
bool get(command_ring_buffer::command& command) { return m_command_ring_buffer.get(command);} bool get(command_ring_buffer::command& command) { return m_command_ring_buffer.get(command);}
bool ok() { return m_server!=NULL; }
private: private:
static int default_handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message data, void *user_data); static int default_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data);
static void error_handler(int num, const char *m, const char *path); static void error_handler(int num, const char *m, const char *path);
lo_server_thread m_server; lo_server_thread m_server;

View File

@ -22,10 +22,6 @@ using namespace std;
lo_address status::m_address = lo_address_new_from_url("osc.udp://localhost:8890"); lo_address status::m_address = lo_address_new_from_url("osc.udp://localhost:8890");
void status::set_port(const std::string &port) {
status::m_address = lo_address_new_from_url(string("osc.udp://localhost:"+port).c_str());
}
void status::_update(const std::string &msg) { void status::_update(const std::string &msg) {
lo_send(m_address,"/report","s",msg.c_str()); lo_send(m_address,"/report","s",msg.c_str());
} }

View File

@ -24,7 +24,6 @@ namespace spiralcore {
class status { class status {
public: public:
static void set_port(const std::string &port);
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);

View File

@ -8,10 +8,6 @@ Install dependencies for the interface:
$ sudo apt install build-essential qtcreator qt5-default $ sudo apt install build-essential qtcreator qt5-default
On ubuntu 22.04 it's:
$ apt install build-essential qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools
Build & run it: Build & run it:
$ mkdir build $ mkdir build
@ -61,12 +57,3 @@ Then edit Info.plist to add samplebrain.icns to CFBundleIconFile. Key `CFBundleI
You might also need to resign the app bundle after making any changes You might also need to resign the app bundle after making any changes
$ codesign --force --deep --sign - samplebrain.app $ codesign --force --deep --sign - samplebrain.app
# Windows (Work in progress)
* Install [MSYS2](https://www.msys2.org/)
* Install dependances via pacman
* Build with qmake as usual
* Run `windeployqt` and copy missing .dll files into release directory

View File

@ -1,14 +1,5 @@
# Changlog # Changlog
0.18.4
* **Windows**: [samplebrain_0.18.4_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_win.zip)
* **Mac (intel/m1)**: [samplebrain_0.18.4_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_macintel.app.zip)
Changes in 0.18.4: New audio device settings window and updated
windows build. Better default block size, tool tip tweaks and fixes
for dark themes by [Claude Heiland-Allen](https://mathr.co.uk/).
0.18.3 0.18.3
* **Windows**: [samplebrain_0.18.3_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.3_win.zip) * **Windows**: [samplebrain_0.18.3_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.3_win.zip)

11
debian/changelog vendored
View File

@ -1,11 +1,6 @@
samplebrain (0.18.5rc1-1ubuntu0~bionic1) bionic; urgency=medium samplebrain (0.18rc2-1ubuntu0~bionic4) bionic; urgency=medium
* Target sound filename shown (and tells you if you don't have one) * Initial release
* More soundfile formats supported (aiff,aifc,au,snd,fasttracker xi,flac)
* New configurable OSC ports in settings
* Warning boxes if the OSC network connection fails
* File path memory per-dialog rather than global
-- Dave Griffiths <dave@thentrythis.org> Thu, 29 Oct 2022 08:47:10 +0100
-- Dave Griffiths <dave@thentrythis.org> Thu, 08 Sep 2022 13:08:26 +0100

View File

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>samplebrain 0.18.5</string> <string>samplebrain 0.18.4</string>
</property> </property>
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
@ -728,13 +728,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="labelTargetSound">
<property name="text">
<string>no target sound loaded</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="pushButtonLoadTarget"> <widget class="QPushButton" name="pushButtonLoadTarget">
<property name="font"> <property name="font">
@ -1119,8 +1112,8 @@
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>17</width> <width>20</width>
<height>13</height> <height>40</height>
</size> </size>
</property> </property>
</spacer> </spacer>

View File

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>438</width> <width>400</width>
<height>656</height> <height>522</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -31,13 +31,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QComboBox" name="deviceComboBox"> <widget class="QComboBox" name="deviceComboBox"/>
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
</widget>
</item> </item>
</layout> </layout>
</item> </item>
@ -63,11 +57,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text"> <property name="text">
<string>44100</string> <string>44100</string>
</property> </property>
@ -84,7 +73,7 @@
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>note: this currently should probably match your sample file's input rate as no conversion is run on them - yet</string> <string>(note: this currently should probably match your sample file's input rate as no conversion is run on them - yet)</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -109,11 +98,6 @@
</item> </item>
<item> <item>
<widget class="QComboBox" name="buffersizeComboBox"> <widget class="QComboBox" name="buffersizeComboBox">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="currentIndex"> <property name="currentIndex">
<number>5</number> <number>5</number>
</property> </property>
@ -196,112 +180,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="label_9">
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="text">
<string>restart needed for the ports below to update</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_6">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>gui osc port</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="guiOSCLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_7">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>process osc port</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="processOSCLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_8">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>audio osc port</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="audioOSCLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QPushButton" name="applyPushButton"> <widget class="QPushButton" name="applyPushButton">
<property name="font"> <property name="font">
@ -340,8 +218,8 @@
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>244</x> <x>231</x>
<y>642</y> <y>358</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>157</x> <x>157</x>
@ -356,8 +234,8 @@
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>312</x> <x>299</x>
<y>642</y> <y>364</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>286</x> <x>286</x>
@ -388,8 +266,8 @@
<slot>apply()</slot> <slot>apply()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>125</x> <x>112</x>
<y>592</y> <y>321</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>4</x> <x>4</x>
@ -420,8 +298,8 @@
<slot>buffersize(QString)</slot> <slot>buffersize(QString)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>390</x> <x>326</x>
<y>215</y> <y>131</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>395</x> <x>395</x>
@ -429,62 +307,11 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>guiOSCLineEdit</sender>
<signal>textChanged(QString)</signal>
<receiver>SettingsDialog</receiver>
<slot>gui_port(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>346</x>
<y>432</y>
</hint>
<hint type="destinationlabel">
<x>401</x>
<y>419</y>
</hint>
</hints>
</connection>
<connection>
<sender>processOSCLineEdit</sender>
<signal>textChanged(QString)</signal>
<receiver>SettingsDialog</receiver>
<slot>process_port(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>356</x>
<y>482</y>
</hint>
<hint type="destinationlabel">
<x>398</x>
<y>479</y>
</hint>
</hints>
</connection>
<connection>
<sender>audioOSCLineEdit</sender>
<signal>textChanged(QString)</signal>
<receiver>SettingsDialog</receiver>
<slot>audio_port(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>374</x>
<y>511</y>
</hint>
<hint type="destinationlabel">
<x>398</x>
<y>517</y>
</hint>
</hints>
</connection>
</connections> </connections>
<slots> <slots>
<slot>output_device(QString)</slot> <slot>output_device(QString)</slot>
<slot>samplerate(QString)</slot> <slot>samplerate(QString)</slot>
<slot>buffersize(QString)</slot> <slot>buffersize(QString)</slot>
<slot>apply()</slot> <slot>apply()</slot>
<slot>gui_port(QString)</slot>
<slot>audio_port(QString)</slot>
<slot>process_port(QString)</slot>
</slots> </slots>
</ui> </ui>