Compare commits

..

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

38 changed files with 930 additions and 1841 deletions

132
README.md
View File

@ -14,7 +14,7 @@ tweakable parameters until it became slightly out of control.
![](docs/pics/screenshot.png) ![](docs/pics/screenshot.png)
# How do I use this thing? Quick start:
1. Load a bunch of short wav files into the brain 1. Load a bunch of short wav files into the brain
2. Click (re)generate brain 2. Click (re)generate brain
@ -23,17 +23,23 @@ tweakable parameters until it became slightly out of control.
5. Press play 5. Press play
6. Tweak brain 6. Tweak brain
Larger wav files like whole tracks can be used, but take a long time The default block size (3000) is really high to prevent CPU glitches -
to process, after which they can be saved as "brain" files and 500 to 1000 is a better range. Larger wav files like whole tracks can
instantly reloaded. be used, but take a long time to process, after which they can be
saved as "brain" files and instantly reloaded.
Check the [Manual](docs/manual.md) here for the details on all the # [Demo brain session](https://static.thentrythis.org/samplebrain/demo.samplebrain)
parameters and try out the [demo brain session](https://static.thentrythis.org/samplebrain/demo.samplebrain).
Load the demo using "load session" not "load brain" (sessions contain Load this file using "load session" not "load brain" (sessions contain
both the target and brain samples). The original samples used to both the target and brain samples). The original samples used to
create the demo session [can be found here for create the demo session [can be found here for
testing](https://static.thentrythis.org/samplebrain/samples/). testing](https://static.thentrythis.org/samplebrain/samples/).
# [Manual](docs/manual.md)
Full description of all the parameters and a bit of the thinking
behind it.
# Download # Download
As this is experimental non-commercial software (only originally As this is experimental non-commercial software (only originally
@ -41,28 +47,17 @@ 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.2_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.2_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.1_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.1_macintel.app.zip)
Changes in 0.18.5 (relased 28/10/22): Thank you to [Nik Gaffney](http://fo.am) for help with the Apple builds
* Target sound filename shown (and tells you if you don't have one)
* 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)
Mac note: As this software is not on the apple store, to run the Mac note: As this software is not on the apple store, to run the
binary you need to tell your mac it's ok: Go to System Preferences > binary you need to tell your mac it's ok: Go to System Preferences >
Security & Privacy > General. At the bottom of the window, select Security & Privacy > General. At the bottom of the window, select
"Allow apps to be downloaded from Anywhere". "Allow apps to be downloaded from Anywhere".
Thank you to [Nik Gaffney](http://fo.am) for help with the Apple ### Linux
builds.
# Linux install
<a href='https://flathub.org/apps/details/org.thentrythis.Samplebrain'><img width='200' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/></a> <a href='https://flathub.org/apps/details/org.thentrythis.Samplebrain'><img width='200' alt='Download on Flathub' src='https://flathub.org/assets/badges/flathub-badge-en.png'/></a>
#### Ubuntu #### Ubuntu
@ -74,13 +69,96 @@ If you'd like the right font, optionally:
$ sudo apt install ttf-mscorefonts-installer $ sudo apt install ttf-mscorefonts-installer
# [Building from source](building.md) # Old/broken/spurious binaries
* **Windows**: [samplebrain_0.18.1_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.1_win.zip)
* **Windows**: [samplebrain_0.18_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18_win.zip)
* **Mac (intel)**: [samplebrain_0.18_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18_macintel.zip)
* **Mac (m1)**: [samplebrain_0.18_m1_v2.dmg](https://static.thentrythis.org/samplebrain/samplebrain_0.18_m1_v2.dmg)
# Building from source
## Linux (Ubuntu)
Install libraries for the sample engine (use brew on mac, MinGW on win):
$ sudo apt install libsndfile1-dev portaudio19-dev liblo-dev libfftw3-dev
Install dependencies for the interface:
$ sudo apt install build-essential qtcreator qt5-default
Build & run it:
$ mkdir build
$ cd build
$ qmake ..
$ make
$ sudo make install
$ samplebrain
## Mac
Install libraries for sample engine:
$ brew install fftw portaudio liblo libsndfile
Install dependencies for the interface:
$ brew install qt
$ brew link qt
Build & run it:
$ mkdir build
$ cd build
$ qmake ..
$ make
`samplebrain.app` should then be in the app folder for you to run.
# Mac build additions
To make a mac app bundle:
Run `macdeployqt` which copies all dependencies inside the app.
$ cd build
$ macdeployqt
If the icon is not visible, you might need to copy desktop/samplebrain.icns (the icon) to the Resources directory in the app bundle.
$ cp ../desktop/samplebrain.icns samplebrain.app/Contents/Resources
Then edit Info.plist to add samplebrain.icns to CFBundleIconFile. Key `CFBundleIconFile` should match:
<key>CFBundleIconFile</key>
<string>samplebrain.icns</string>
You might also need to resign the app bundle after making any changes
$ codesign --force --deep --sign - samplebrain.app
## What's here
1. brain:
* samplebrain engine code
2. app:
* code to build the Qt GUI app
3. gui:
* qt designer project files
4. desktop:
* various icon files etc
4. cooking:
* some sketches and ideas
* proof of concept written in python
* brief initial (abandoned) attempt at clojure version
MFCC algo courtesy of the Aquila library by Zbigniew Siciarz MIT/X11 MFCC algo courtesy of the Aquila library by Zbigniew Siciarz MIT/X11
licence 2007-2014 (see brain/src/aquila/LICENCE). This program is free licence 2007-2014 (see brain/src/aquila/LICENCE)
software licenced under GNU General Public License version 2 (see
LICENCE). Written by [Dave Griffiths at Then Try This](http://thentrythis.org). This program is free software licenced under GNU General Public
License version 2 (see LICENCE).
Written by [Dave Griffiths at Then Try This](http://thentrythis.org).
## Links ## Links
To find related tech like [CataRT](https://ircam-ismm.github.io/max-msp/catart.html), [bbcut2](https://composerprogrammer.com/bbcut2.html), [eargram](https://sites.google.com/site/eargram/) and [sCrAmBlEd?HaCkZ!](https://www.youtube.com/watch?v=eRlhKaxcKpA) search up [granular synthesis](http://granularsynthesis.com/guide.php), [concatenative synthesis](https://hal.archives-ouvertes.fr/hal-01161337), [neural audio synthesis](https://github.com/acids-ircam/RAVE), [sinewave speech](http://www.lifesci.sussex.ac.uk/home/Chris_Darwin/SWS/), automated breakbeat cutting, audio mosaicing and plunderphonics/plundermatics. To find related tech like [CataRT](http://imtr.ircam.fr/imtr/CataRT), [bbcut2](https://composerprogrammer.com/bbcut2.html), [eargram](https://sites.google.com/site/eargram/) and [sCrAmBlEd?HaCkZ!](https://www.youtube.com/watch?v=eRlhKaxcKpA) search up [granular synthesis](http://granularsynthesis.com/guide.php), [concatenative synthesis](https://hal.archives-ouvertes.fr/hal-01161337), [neural audio synthesis](https://github.com/acids-ircam/RAVE), [sinewave speech](http://www.lifesci.sussex.ac.uk/home/Chris_Darwin/SWS/), automated breakbeat cutting, audio mosaicing and plunderphonics/plundermatics.

View File

@ -14,9 +14,6 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef MAIN_WINDOW
#define MAIN_WINDOW
#include <QtGui> #include <QtGui>
#include <iostream> #include <iostream>
#include <list> #include <list>
@ -27,16 +24,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,8 +46,6 @@ 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);
// add default local dest // add default local dest
// turn on first one // turn on first one
@ -66,8 +54,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 +149,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());
@ -201,5 +183,3 @@ void MainWindow::init_from_session(const string &filename) {
} }
#endif

View File

@ -18,9 +18,7 @@
#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 <iostream> #include <iostream>
#include <lo/lo.h> #include <lo/lo.h>
@ -28,445 +26,390 @@
#include <list> #include <list>
#include "feedback.h" #include "feedback.h"
#include "sound_items.h" #include "sound_items.h"
#include "audio_thread.h"
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...
void send_audio_osc(const char *name, const char *types) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_audio_address,name,types);
}
}
}
template <class T>
void send_audio_osc(const char *name, const char *types, T val) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_audio_address,name,types,val);
}
}
}
void send_process_osc(const char *name, const char *types) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_process_address,name,types);
}
}
}
template <class T>
void send_process_osc(const char *name, const char *types, T val) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_process_address,name,types,val);
}
}
}
void set_audio_thread(audio_thread *at) {
m_audio_thread=at;
m_audio_thread->start_audio();
for (auto &d:m_audio_thread->m_audio_device->m_client.m_devices) {
if (d.id==0) {
m_settings_dialog->m_Ui.deviceComboBox->clear();
}
m_settings_dialog->m_Ui.deviceComboBox->addItem(d.name.c_str());
if (d.default_output==1) {
m_settings_dialog->m_device=d.name;
m_settings_dialog->m_Ui.deviceComboBox->setCurrentText(d.name.c_str());
}
}
m_settings_dialog->m_Ui.messagesLabel->setText(m_audio_thread->m_audio_device->m_client.m_status.c_str());
}
audio_thread *get_audio_thread() {
return m_audio_thread;
}
protected: protected:
private slots: private slots:
void play_slot() { send_audio_osc("/start",""); } void play_slot() { send_audio_osc("/start",""); }
void stop_slot() { send_audio_osc("/pause",""); } void stop_slot() { send_audio_osc("/pause",""); }
void ratio_slot(int s) { void ratio_slot(int s) {
send_audio_osc("/ratio","f",s/100.0f); send_audio_osc("/ratio","f",s/100.0f);
m_Ui.doubleSpinBoxRatio->setValue(s/100.0f); m_Ui.doubleSpinBoxRatio->setValue(s/100.0f);
}
void ratio_slot(double s) {
send_audio_osc("/ratio","f",s);
m_Ui.sliderRatio->setValue(s*100);
}
void n_ratio_slot(int s) {
send_audio_osc("/n_ratio","f",s/100.0f);
m_Ui.doubleSpinBoxNRatio->setValue(s/100.0f);
}
void n_ratio_slot(double s) {
send_audio_osc("/n_ratio","f",s);
m_Ui.sliderNRatio->setValue(s*100);
}
void autotune(int s) {
send_audio_osc("/autotune","f",s/100.0f);
m_Ui.doubleSpinBoxAutotune->setValue(s/100.0f);
}
void autotune(double s) {
send_audio_osc("/autotune","f",s);
m_Ui.sliderAutotune->setValue(s*100);
}
void fft1_start_slot(int s) { send_audio_osc("/fft1_start","i",s); }
void fft1_end_slot(int s) { send_audio_osc("/fft1_end","i",s); }
void fft2_start_slot(int s){} // { m_renderer->get_params()->m_fft2_start=s; }
void fft2_end_slot(int s){} // { m_renderer->get_params()->m_fft2_end=s; }
void n_mix_slot(int s) {
send_audio_osc("/n_mix","f",s/100.0f);
m_Ui.doubleSpinBoxNMix->setValue(s/100.0f);
}
void n_mix_slot(double s) {
send_audio_osc("/n_mix","f",s);
m_Ui.sliderNMix->setValue(s*100);
}
void novelty_slot(int s) {
send_audio_osc("/novelty","f",s/100.0f);
m_Ui.doubleSpinBoxNovelty->setValue(s/100.0f);
}
void novelty_slot(double s) {
send_audio_osc("/novelty","f",s);
m_Ui.sliderNovelty->setValue(s*100);
}
void boredom_slot(int s) {
float v=s/100.0f;
send_audio_osc("/boredom","f",v);
m_Ui.doubleSpinBoxBoredom->setValue(v);
}
void boredom_slot(double s) {
send_audio_osc("/boredom","f",s);
m_Ui.sliderBoredom->setValue(s*100);
}
void synapses(int s) {
send_audio_osc("/synapses","i",s);
}
void target_mix_slot(int s) {
send_audio_osc("/target_mix","f",s/100.0f);
m_Ui.doubleSpinBoxTargetMix->setValue(s/100.0f);
}
void target_mix_slot(double s) {
send_audio_osc("/target_mix","f",s);
m_Ui.sliderTargetMix->setValue(s*100);
}
void search_stretch(int s) {
send_audio_osc("/search-stretch","i",s);
}
void slide_error(int s) {
send_audio_osc("/slide-error","i",s);
}
void stickyness_slot(int s) {
send_audio_osc("/stickyness","f",s/100.0f);
m_Ui.doubleSpinBoxStickyness->setValue(s/100.0f);
}
void stickyness_slot(double s) {
send_audio_osc("/stickyness","f",s);
m_Ui.sliderStickyness->setValue(s*100);
}
void volume_slot(int s) { send_audio_osc("/volume","f",s/100.0f); }
void algo(int n) { send_audio_osc("/search_algo","i",n); }
void run_slot() {}
void load_target() {
QString path=QFileDialog::getOpenFileName(this,
QString("Select an audio file"),
m_last_target_file,
m_format_string);
if (m_last_target_file!="") {
m_last_target_file=path;
m_Ui.labelTargetSound->setText("loaded: "+QFileInfo(path).fileName());
send_process_osc("/load_target","s",m_last_target_file.toStdString().c_str());
} }
} void ratio_slot(double s) {
void target_block_size(int s) { send_process_osc("/target_block_size","i",s); } send_audio_osc("/ratio","f",s);
void target_block_overlap(double s) { send_process_osc("/target_overlap","f",s); } m_Ui.sliderRatio->setValue(s*100);
void generate_target_blocks() { send_process_osc("/generate_target",""); } }
void block_size(int s) { send_process_osc("/source_block_size","i",s); }
void block_overlap(double s) { send_process_osc("/source_overlap","f",s); } void n_ratio_slot(int s) {
void fft_spectrum_size(int) {} send_audio_osc("/n_ratio","f",s/100.0f);
void generate() { send_process_osc("/generate_brain",""); } m_Ui.doubleSpinBoxNRatio->setValue(s/100.0f);
void load_sound() { }
QString path=QFileDialog::getOpenFileName(this, void n_ratio_slot(double s) {
QString("Select a wav file"), send_audio_osc("/n_ratio","f",s);
m_last_sound_file, m_Ui.sliderNRatio->setValue(s*100);
m_format_string); }
if (path!="") { void autotune(int s) {
m_last_sound_file=path; send_audio_osc("/autotune","f",s/100.0f);
send_process_osc("/load_sample","s",m_last_sound_file.toStdString().c_str()); m_Ui.doubleSpinBoxAutotune->setValue(s/100.0f);
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())); void autotune(double s) {
m_sound_item_enable_mapper->setMapping(si.m_enable, si.m_id); send_audio_osc("/autotune","f",s);
QObject::connect(si.m_del, SIGNAL(clicked()), m_sound_item_delete_mapper, SLOT(map())); m_Ui.sliderAutotune->setValue(s*100);
m_sound_item_delete_mapper->setMapping(si.m_del, si.m_id); }
void fft1_start_slot(int s) { send_audio_osc("/fft1_start","i",s); }
void fft1_end_slot(int s) { send_audio_osc("/fft1_end","i",s); }
void fft2_start_slot(int s){} // { m_renderer->get_params()->m_fft2_start=s; }
void fft2_end_slot(int s){} // { m_renderer->get_params()->m_fft2_end=s; }
void n_mix_slot(int s) {
send_audio_osc("/n_mix","f",s/100.0f);
m_Ui.doubleSpinBoxNMix->setValue(s/100.0f);
}
void n_mix_slot(double s) {
send_audio_osc("/n_mix","f",s);
m_Ui.sliderNMix->setValue(s*100);
}
void novelty_slot(int s) {
send_audio_osc("/novelty","f",s/100.0f);
m_Ui.doubleSpinBoxNovelty->setValue(s/100.0f);
}
void novelty_slot(double s) {
send_audio_osc("/novelty","f",s);
m_Ui.sliderNovelty->setValue(s*100);
}
void boredom_slot(int s) {
float v=s/100.0f;
send_audio_osc("/boredom","f",v);
m_Ui.doubleSpinBoxBoredom->setValue(v);
}
void boredom_slot(double s) {
send_audio_osc("/boredom","f",s);
m_Ui.sliderBoredom->setValue(s*100);
}
void synapses(int s) {
send_audio_osc("/synapses","i",s);
}
void target_mix_slot(int s) {
send_audio_osc("/target_mix","f",s/100.0f);
m_Ui.doubleSpinBoxTargetMix->setValue(s/100.0f);
}
void target_mix_slot(double s) {
send_audio_osc("/target_mix","f",s);
m_Ui.sliderTargetMix->setValue(s*100);
}
void search_stretch(int s) {
send_audio_osc("/search-stretch","i",s);
}
void slide_error(int s) {
send_audio_osc("/slide-error","i",s);
}
void stickyness_slot(int s) {
send_audio_osc("/stickyness","f",s/100.0f);
m_Ui.doubleSpinBoxStickyness->setValue(s/100.0f);
}
void stickyness_slot(double s) {
send_audio_osc("/stickyness","f",s);
m_Ui.sliderStickyness->setValue(s*100);
}
void volume_slot(int s) { send_audio_osc("/volume","f",s/100.0f); }
void algo(int n) { send_audio_osc("/search_algo","i",n); }
void run_slot() {}
void load_target() {
m_last_file=QFileDialog::getOpenFileName(
this,
QString("Select an wav file"),
m_last_file,
QString("Sounds (*.wav)"));
send_process_osc("/load_target","s",m_last_file.toStdString().c_str());
}
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 generate_target_blocks() { send_process_osc("/generate_target",""); }
void block_size(int s) { send_process_osc("/source_block_size","i",s); }
void block_overlap(double s) { send_process_osc("/source_overlap","f",s); }
void fft_spectrum_size(int) {}
void generate() { send_process_osc("/generate_brain",""); }
void load_sound() {
m_last_file=QFileDialog::getOpenFileName(
this,
QString("Select a wav file"),
m_last_file,
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);
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);
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);
} }
}
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_directory_file,QDirIterator::Subdirectories);
while (dirIt.hasNext()) {
dirIt.next();
if (QFileInfo(dirIt.filePath()).isFile() &&
QFileInfo(dirIt.filePath()).suffix() == "wav") {
send_process_osc("/load_sample","s",dirIt.filePath().toStdString().c_str());
sound_items::sound_item &si = m_sound_items.add(m_Ui.brain_contents, dirIt.filePath().toStdString(),true); QDirIterator dirIt(m_last_file,QDirIterator::Subdirectories);
while (dirIt.hasNext()) {
dirIt.next();
if (QFileInfo(dirIt.filePath()).isFile() &&
QFileInfo(dirIt.filePath()).suffix() == "wav") {
send_process_osc("/load_sample","s",dirIt.filePath().toStdString().c_str());
QObject::connect(si.m_enable, SIGNAL(clicked()), m_sound_item_enable_mapper, SLOT(map())); sound_items::sound_item &si = m_sound_items.add(m_Ui.brain_contents, dirIt.filePath().toStdString(),true);
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()));
m_sound_item_delete_mapper->setMapping(si.m_del, si.m_id);
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);
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);
}
}
}
void select_all() {
for (auto &si:m_sound_items.m_sound_items) {
si.m_enable->setChecked(true);
send_process_osc("/activate_sound","s",si.m_filename.c_str());
}
}
void select_none() {
for (auto &si:m_sound_items.m_sound_items) {
si.m_enable->setChecked(false);
send_process_osc("/deactivate_sound","s",si.m_filename.c_str());
}
}
void sound_enable(int id) {
// search for this id...
for (auto &si:m_sound_items.m_sound_items) {
if (si.m_id==id) {
if (si.m_enable->isChecked()) {
send_process_osc("/activate_sound","s",si.m_filename.c_str());
} else {
send_process_osc("/deactivate_sound","s",si.m_filename.c_str());
}
} }
} }
} }
}
void select_all() { void delete_sound(int id) {
for (auto &si:m_sound_items.m_sound_items) { // search for this id...
si.m_enable->setChecked(true); for (auto &si:m_sound_items.m_sound_items) {
send_process_osc("/activate_sound","s",si.m_filename.c_str()); if (si.m_id==id) {
} send_process_osc("/delete_sample","s",si.m_filename.c_str());
} m_sound_items.remove(si.m_filename);
// iterator is now invalidated...
void select_none() { return;
for (auto &si:m_sound_items.m_sound_items) {
si.m_enable->setChecked(false);
send_process_osc("/deactivate_sound","s",si.m_filename.c_str());
}
}
void sound_enable(int id) {
// search for this id...
for (auto &si:m_sound_items.m_sound_items) {
if (si.m_id==id) {
if (si.m_enable->isChecked()) {
send_process_osc("/activate_sound","s",si.m_filename.c_str());
} else {
send_process_osc("/deactivate_sound","s",si.m_filename.c_str());
} }
} }
} }
} void clear_brain() {
for (auto &si:m_sound_items.m_sound_items) {
void delete_sound(int id) {
// search for this id...
for (auto &si:m_sound_items.m_sound_items) {
if (si.m_id==id) {
send_process_osc("/delete_sample","s",si.m_filename.c_str()); send_process_osc("/delete_sample","s",si.m_filename.c_str());
m_sound_items.remove(si.m_filename);
// iterator is now invalidated...
return;
} }
m_sound_items.clear();
} }
} void restart_audio() { send_audio_osc("/restart_audio",""); }
void clear_brain() {
for (auto &si:m_sound_items.m_sound_items) { void brain_shape(int n) { send_process_osc("/window_type","i",n); }
send_process_osc("/delete_sample","s",si.m_filename.c_str()); void target_shape(int n) { send_process_osc("/target_window_type","i",n); }
void mic(bool n) { send_audio_osc("/mic","i",(int)n); }
void record() {
if (m_save_wav=="") {
m_last_file=QFileDialog::getSaveFileName(
this,
QString("Select a wav file"),
m_last_file,
QString("Sounds (*.wav)"));
m_save_wav = m_last_file.toStdString();
// chop off .wav
size_t pos = m_save_wav.find_last_of(".");
if (pos!=string::npos) {
m_save_wav = m_save_wav.substr(0,pos);
}
}
char fn[1024];
snprintf(fn,1024,"%s-%i",m_save_wav.c_str(),m_record_id);
send_audio_osc("/record","s",fn);
cerr<<fn<<endl;
m_record_id++;
} }
m_sound_items.clear();
}
void restart_audio() { send_audio_osc("/restart_audio",""); }
void brain_shape(int n) { send_process_osc("/window_type","i",n); } void stop_record() {
void target_shape(int n) { send_process_osc("/target_window_type","i",n); } send_audio_osc("/stop","");
void mic(bool n) { send_audio_osc("/mic","i",(int)n); } }
void record() { void load_brain() {
if (m_save_wav=="") { m_last_file=QFileDialog::getOpenFileName(
m_last_recording_file=QFileDialog::getSaveFileName(this, this,
QString("Select a wav file"), QString("Select a brain file"),
m_last_recording_file, m_last_file,
QString("Sounds (*.wav);;All files (*.*)")); QString("Brains (*.brain)"));
m_save_wav = m_last_recording_file.toStdString();
// chop off .wav send_process_osc("/load_brain","s",m_last_file.toStdString().c_str());
size_t pos = m_save_wav.find_last_of("."); }
if (pos!=string::npos) { void save_brain() {
m_save_wav = m_save_wav.substr(0,pos); m_last_file=QFileDialog::getSaveFileName(
this,
QString("Select a brain file"),
m_last_file,
QString("Brains (*.brain)"));
send_process_osc("/save_brain","s",m_last_file.toStdString().c_str());
}
void load_session() {
m_last_file=QFileDialog::getOpenFileName(
this,
QString("Select a session file"),
m_last_file,
QString("Sessions *.samplebrain (*.samplebrain)"));
send_process_osc("/load_session","s",m_last_file.toStdString().c_str());
init_from_session(m_last_file.toStdString());
}
void save_session() {
m_last_file=QFileDialog::getSaveFileName(
this,
QString("Select a session file"),
m_last_file,
QString("Sessions *.samplebrain (*.samplebrain)"));
send_process_osc("/save_session","s",m_last_file.toStdString().c_str());
}
void update_status() {
m_feedback.poll(m_Ui.statusbar,&m_sound_items);
}
void stereo_mode(bool s) {
send_audio_osc("/stereo","i",s);
}
void net_enable(int id) {
osc_destination &d = m_destinations[id];
if (d.m_enable->isChecked()) {
// reconnect
string url = d.m_address->text().toUtf8().constData();
lo_address_free(d.m_audio_address);
lo_address_free(d.m_process_address);
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+":8889").c_str());
// start sending messages here
d.m_enabled=true;
} else {
// stop sending messages here
d.m_enabled=false;
} }
} }
char fn[1024];
snprintf(fn,1024,"%s-%i",m_save_wav.c_str(),m_record_id);
send_audio_osc("/record","s",fn);
cerr<<fn<<endl;
m_record_id++;
}
void stop_record() {
send_audio_osc("/stop","");
}
void load_brain() {
QString path=QFileDialog::getOpenFileName(this,
QString("Select a brain file"),
m_last_brain_file,
QString("Brains (*.brain);;All files (*.*)"));
if (path!="") {
m_last_brain_file=path;
send_process_osc("/load_brain","s",m_last_brain_file.toStdString().c_str());
}
}
void save_brain() {
QString path=QFileDialog::getSaveFileName(this,
QString("Select a brain file"),
m_last_brain_file,
QString("Brains (*.brain);;All files (*.*)"));
if (path!="") {
m_last_brain_file=path;
send_process_osc("/save_brain","s",m_last_brain_file.toStdString().c_str());
}
}
void load_session() {
QString path=QFileDialog::getOpenFileName(this,
QString("Select a session file"),
m_last_session_file,
QString("Sessions *.samplebrain (*.samplebrain);;All files (*.*)"));
if (path!="") {
m_last_session_file=path;
send_process_osc("/load_session","s",m_last_session_file.toStdString().c_str());
init_from_session(m_last_session_file.toStdString());
}
}
void save_session() {
QString path=QFileDialog::getSaveFileName(this,
QString("Select a session file"),
m_last_session_file,
QString("Sessions *.samplebrain (*.samplebrain)"));
if (path!="") {
m_last_session_file=path;
send_process_osc("/save_session","s",m_last_session_file.toStdString().c_str());
}
}
void update_status() {
m_feedback.poll(m_Ui.statusbar,&m_sound_items,m_settings_dialog);
}
void stereo_mode(bool s) {
send_audio_osc("/stereo","i",s);
}
void net_enable(int id) {
osc_destination &d = m_destinations[id];
if (d.m_enable->isChecked()) {
// reconnect
string url = d.m_address->text().toUtf8().constData();
lo_address_free(d.m_audio_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_process_address = lo_address_new_from_url(string(url+":"+m_process_port).c_str());
// start sending messages here
d.m_enabled=true;
} else {
// stop sending messages here
d.m_enabled=false;
}
}
void settings() {
m_settings_dialog->show();
}
private: private:
/////////////////////////////////////////////// ///////////////////////////////////////////////
// we want to be able to send out to // we want to be able to send out to
// multiple addresses over the network // multiple addresses over the network
//////////////////////////////////////////////// ////////////////////////////////////////////////
// we want to be able to send out to // we want to be able to send out to
// multiple addresses over the network // multiple addresses over the network
class osc_destination { class osc_destination {
public: public:
int m_id; int m_id;
lo_address m_audio_address; lo_address m_audio_address;
lo_address m_process_address; lo_address m_process_address;
// can't find a way to address these via qt // can't find a way to address these via qt
QLineEdit *m_address; QLineEdit *m_address;
QCheckBox *m_enable; QCheckBox *m_enable;
bool m_enabled; bool m_enabled;
}; };
vector<osc_destination> m_destinations; vector<osc_destination> m_destinations;
// all this to work around liblo's use of varargs...
void send_audio_osc(const char *name, const char *types) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_audio_address,name,types);
}
}
}
template <class T>
void send_audio_osc(const char *name, const char *types, T val) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_audio_address,name,types,val);
}
}
}
void send_process_osc(const char *name, const char *types) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_process_address,name,types);
}
}
}
template <class T>
void send_process_osc(const char *name, const char *types, T val) {
for (auto dest:m_destinations) {
if (dest.m_enabled) {
lo_send(dest.m_process_address,name,types,val);
}
}
}
void init_from_session(const string &filename); void init_from_session(const string &filename);
void add_gui_address(osc_destination &dest, void add_gui_address(osc_destination &dest,
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; unsigned int m_record_id;
QString m_last_directory_file; Ui_MainWindow m_Ui;
QString m_last_brain_file; feedback m_feedback;
QString m_last_session_file; QSignalMapper* m_sound_item_enable_mapper;
QString m_last_recording_file; QSignalMapper* m_sound_item_delete_mapper;
unsigned int m_record_id; sound_items m_sound_items;
Ui_MainWindow m_Ui;
feedback m_feedback;
QSignalMapper* m_sound_item_enable_mapper;
QSignalMapper* m_sound_item_delete_mapper;
sound_items m_sound_items;
SettingsDialog *m_settings_dialog;
audio_thread *m_audio_thread;
string m_audio_port;
string m_process_port;
QString m_format_string;
}; };

View File

@ -1,43 +0,0 @@
// Copyright (C) 2022 Then Try This
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <QtGui>
#include <iostream>
#include <list>
#include "MainWindow.h"
#include "SettingsDialog.h"
#include "feedback.h"
using namespace std;
SettingsDialog::SettingsDialog(MainWindow *parent, QSettings *settings):
m_device(""),
m_parent(parent),
m_buffersize(2048),
m_samplerate(44100),
m_settings(settings) {
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() {
audio_thread *at = m_parent->get_audio_thread();
at->restart_audio(m_device,m_samplerate,m_buffersize);
m_Ui.messagesLabel->setText(at->m_audio_device->m_client.m_status.c_str());
}

View File

@ -1,89 +0,0 @@
// Copyright (C) 2022 Then Try This
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef SETTINGS_DIALOG
#define SETTINGS_DIALOG
#include <QtGui>
#include <QDialog>
#include <QLineEdit>
#include <QSettings>
#include "ui_settings.h"
#include <iostream>
#include <lo/lo.h>
#include <string>
#include <list>
using namespace std;
class MainWindow;
class SettingsDialog : public QDialog
{
Q_OBJECT
public:
SettingsDialog(MainWindow *parent, QSettings *settings);
Ui_SettingsDialog m_Ui;
string m_device;
protected:
private slots:
void samplerate(QString str) {
try { m_samplerate=stoi(str.toStdString()); }
catch(std::exception const & e) {
m_samplerate=44100;
}
}
void output_device(QString v) { m_device=v.toStdString(); }
void buffersize(QString str) {
try { m_buffersize=stoi(str.toStdString()); }
catch(std::exception const & e) {
m_buffersize=44100;
}
}
void accept() { connect(); hide(); }
void reject() { hide(); }
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:
void connect();
MainWindow *m_parent;
unsigned int m_buffersize;
unsigned int m_samplerate;
QSettings *m_settings;
};
#endif

View File

@ -20,17 +20,15 @@
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_samplerate(44100), start_audio();
m_device("") {
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);
@ -50,28 +48,18 @@ audio_thread::~audio_thread() {
void audio_thread::start_audio() { void audio_thread::start_audio() {
if (m_audio_device!=NULL) delete m_audio_device; if (m_audio_device!=NULL) delete m_audio_device;
m_audio_device = new audio_device("samplebrain",m_samplerate,m_bufsize); m_audio_device = new audio_device("samplebrain",48000,2048);
//m_audio_device = new audio_device("samplebrain",48000,2048*4);
m_audio_device->m_client.set_callback(run_audio, this); m_audio_device->m_client.set_callback(run_audio, this);
} }
void audio_thread::restart_audio(const string device, unsigned int samplerate, unsigned int bufsize) {
m_samplerate = samplerate;
m_bufsize = bufsize;
m_device = device;
m_audio_device->connect(m_device,
"samplebrain",
m_samplerate,
m_bufsize);
}
void audio_thread::run_audio(void* c, unsigned int frames) { void audio_thread::run_audio(void* c, unsigned int frames) {
if (state) { if (state) {
audio_thread *at = (audio_thread*)c; audio_thread *at = (audio_thread*)c;
at->m_audio_device->left_out.zero(); at->m_audio_device->left_out.zero();
at->process(at->m_audio_device->left_in, at->process(at->m_audio_device->left_in,
at->m_audio_device->right_in, at->m_audio_device->right_in,
at->m_audio_device->left_out, at->m_audio_device->left_out,
at->m_audio_device->right_out); at->m_audio_device->right_out);
at->m_audio_device->maybe_record(); at->m_audio_device->maybe_record();
} }
@ -198,12 +186,12 @@ void audio_thread::process(sample &left_in, sample &right_in, sample &left_out,
} }
m_left_renderer->process(left_out.get_length(), m_left_renderer->process(left_out.get_length(),
left_out.get_non_const_buffer(), left_out.get_non_const_buffer(),
bs); bs);
if (m_stereo_mode) { if (m_stereo_mode) {
m_right_renderer->process(right_out.get_length(), m_right_renderer->process(right_out.get_length(),
right_out.get_non_const_buffer(), right_out.get_non_const_buffer(),
bs); bs);
} else { } else {
right_out=left_out; right_out=left_out;
} }

View File

@ -24,14 +24,11 @@
namespace spiralcore { 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 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);
@ -41,16 +38,14 @@ namespace spiralcore {
renderer *m_right_renderer; renderer *m_right_renderer;
block_stream *m_block_stream; block_stream *m_block_stream;
private: private:
void start_audio();
OSC_server m_osc; OSC_server m_osc;
process_thread &m_process_thread; process_thread &m_process_thread;
pthread_mutex_t* m_brain_mutex; pthread_mutex_t* m_brain_mutex;
bool m_stereo_mode; bool m_stereo_mode;
bool m_mic_mode; bool m_mic_mode;
u32 m_bufsize; };
u32 m_samplerate;
string m_device;
};
} }

View File

@ -16,7 +16,6 @@
#include "feedback.h" #include "feedback.h"
#include "sound_items.h" #include "sound_items.h"
#include "SettingsDialog.h"
#include <iostream> #include <iostream>
using namespace spiralcore; using namespace spiralcore;
@ -29,7 +28,7 @@ feedback::feedback(string address) :
} }
void feedback::poll(QStatusBar *s, sound_items *sound_items, SettingsDialog *settings) { void feedback::poll(QStatusBar *s, sound_items *sound_items) {
command_ring_buffer::command cmd; command_ring_buffer::command cmd;
while (m_osc.get(cmd)) { while (m_osc.get(cmd)) {

View File

@ -17,7 +17,6 @@
#include <string> #include <string>
#include <QtGui> #include <QtGui>
#include <QStatusBar> #include <QStatusBar>
#include "SettingsDialog.h"
#include "spiralcore/OSC_server.h" #include "spiralcore/OSC_server.h"
#pragma once #pragma once
@ -27,13 +26,12 @@ class sound_items;
class feedback { 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);
bool ok() { return m_osc.ok(); }
private: private:
OSC_server m_osc; OSC_server m_osc;
}; };
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

View File

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

View File

@ -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,23 @@
#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);
MainWindow mainWin;
mainWin.show();
cerr<<"Qt version: "<<qVersion()<<endl;
QApplication app(argc, argv); process_thread pt;
audio_thread at(pt);
pt.register_renderer(at.m_left_renderer, at.m_right_renderer, at.m_block_stream);
QSettings settings("thentrythis", "samplebrain"); return app.exec();
// 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();
process_thread pt(process_port);
audio_thread at(audio_port,pt);
pt.register_renderer(at.m_left_renderer, at.m_right_renderer, at.m_block_stream);
mainWin.set_audio_thread(&at);
if (!at.ok()) {
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();
} }

View File

@ -1,6 +1,5 @@
<RCC> <RCC>
<qresource prefix="images"> <qresource prefix="images">
<file>images/settings.png</file>
<file>images/at.png</file> <file>images/at.png</file>
<file>images/pause.png</file> <file>images/pause.png</file>
<file>images/play.png</file> <file>images/play.png</file>

View File

@ -33,7 +33,7 @@ sound_items::sound_item &sound_items::add(QVBoxLayout *container, const string &
sound_item si; sound_item si;
si.m_filename = name; si.m_filename = name;
si.m_id = m_current_sound_id++; si.m_id = m_current_sound_id++;
QString style("color:black;background-color:lightgrey;"); QString style("background-color:lightgrey;");
si.m_container = new QHBoxLayout(); si.m_container = new QHBoxLayout();
si.m_container->setSpacing(10); si.m_container->setSpacing(10);
@ -89,8 +89,8 @@ void sound_items::clear() {
void sound_items::recolour() { void sound_items::recolour() {
u32 c=0; u32 c=0;
for (auto &si:m_sound_items) { for (auto &si:m_sound_items) {
QString style("color:black;background-color:lightblue;"); QString style("background-color:lightblue;");
if (c%2==0) style="color:black;background-color:pink;"; if (c%2==0) style="background-color:pink;";
si.m_enable->setStyleSheet(style); si.m_enable->setStyleSheet(style);
si.m_del->setStyleSheet(style); si.m_del->setStyleSheet(style);
si.m_label->setStyleSheet(style); si.m_label->setStyleSheet(style);
@ -101,7 +101,7 @@ void sound_items::recolour() {
void sound_items::change_colour(const std::string &name, const std::string &colour) { void sound_items::change_colour(const std::string &name, const std::string &colour) {
for (auto &si:m_sound_items) { for (auto &si:m_sound_items) {
if (si.m_filename==name) { if (si.m_filename==name) {
QString style("color:black;background-color:"+QString::fromStdString(colour)+";"); QString style("background-color:"+QString::fromStdString(colour)+";");
si.m_enable->setStyleSheet(style); si.m_enable->setStyleSheet(style);
si.m_del->setStyleSheet(style); si.m_del->setStyleSheet(style);
si.m_label->setStyleSheet(style); si.m_label->setStyleSheet(style);

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@ -31,106 +31,117 @@ 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; {
m_server = lo_server_thread_new(port.c_str(), error_handler); //cerr<<"using port: ["<<port<<"]"<<endl;
if (m_server) { m_server = lo_server_thread_new(port.c_str(), error_handler);
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; {
lo_server_thread_stop(m_server); m_exit=true;
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<<endl; //cerr<<"liblo server error "<<num<<" in path "<<path<<": "<<msg<<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; {
if (!server) return -1; OSC_server *server = (OSC_server*)user_data;
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]); {
// add one for the null terminator size+=lo_arg_size((lo_type)types[i],argv[i]);
if (types[i]=='s') size++; // add one for the null terminator
} if (types[i]=='s') size++;
}
char *newdata=new char[size];
unsigned int pos=0;
for (int i=0; i<argc; i++)
{
switch (types[i])
{
case LO_INT32:
{
if (pos+4>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,(char*)argv[i],4);
pos+=4;
}
break;
case LO_FLOAT:
{
if (pos+4>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,(char*)argv[i],4);
pos+=4;
}
break;
case LO_STRING:
{
int size=strlen(&argv[i]->s);
if (pos+size+1>COMMAND_DATA_SIZE)
{
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,&argv[i]->s,size);
newdata[pos+size]='\0';
pos+=size+1;
}
break;
default:
{
cerr<<"unsupported type: "<<types[i]<<endl;
delete[] newdata;
return 1;
}
break;
}
}
if (1)//pos==size) hmm
{
command_ring_buffer::command command(path,types,newdata,pos);
if (!server->m_command_ring_buffer.send(command))
{
//cerr<<"OSC_server - ringbuffer full!"<<endl;
}
}
else
{
cerr<<"OSC_server::default_handler: size mismatch ["<<pos<<":"<<size<<"], not sending message"<<endl;
}
char *newdata=new char[size];
unsigned int pos=0;
for (int i=0; i<argc; i++) {
switch (types[i]) {
case LO_INT32: {
if (pos+4>COMMAND_DATA_SIZE) {
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata; delete[] newdata;
return 1; return 1;
}
memcpy(newdata+pos,(char*)argv[i],4);
pos+=4;
}
break;
case LO_FLOAT: {
if (pos+4>COMMAND_DATA_SIZE) {
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,(char*)argv[i],4);
pos+=4;
}
break;
case LO_STRING: {
int size=strlen(&argv[i]->s);
if (pos+size+1>COMMAND_DATA_SIZE) {
cerr<<"osc data too big for ringbuffer command"<<endl;
delete[] newdata;
return 1;
}
memcpy(newdata+pos,&argv[i]->s,size);
newdata[pos+size]='\0';
pos+=size+1;
}
break;
default: {
cerr<<"unsupported type: "<<types[i]<<endl;
delete[] newdata;
return 1;
}
break;
}
}
if (1) { //pos==size) hmm
command_ring_buffer::command command(path,types,newdata,pos);
if (!server->m_command_ring_buffer.send(command)) {
//cerr<<"OSC_server - ringbuffer full!"<<endl;
}
}
else {
cerr<<"OSC_server::default_handler: size mismatch ["<<pos<<":"<<size<<"], not sending message"<<endl;
}
delete[] newdata;
return 1;
} }

View File

@ -24,21 +24,20 @@
class OSC_server class OSC_server
{ {
public: public:
OSC_server(const std::string &port); OSC_server(const std::string &port);
~OSC_server(); ~OSC_server();
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;
std::string m_port; std::string m_port;
bool m_exit; bool m_exit;
command_ring_buffer m_command_ring_buffer; command_ring_buffer m_command_ring_buffer;
}; };
#endif #endif

View File

@ -22,40 +22,31 @@ using namespace std;
using namespace spiralcore; using namespace spiralcore;
audio_device::audio_device(const string &clientname, u32 samplerate, u32 buffer_size) : audio_device::audio_device(const string &clientname, u32 samplerate, u32 buffer_size) :
left_out(buffer_size),
right_out(buffer_size),
left_in(buffer_size),
right_in(buffer_size),
m_recording(false), m_recording(false),
m_record_filename(""), m_record_filename("")
m_samplerate(samplerate) { {
// connect to default device portaudio_client::device_options opt;
m_client.init(); opt.buffer_size = buffer_size;
connect("", clientname, samplerate, buffer_size); opt.num_buffers = 2;
} opt.samplerate = samplerate;
opt.in_channels = 2;
opt.out_channels = 2;
void audio_device::connect(const string &output_device_name, const string &clientname, u32 samplerate, u32 buffer_size) { m_client.set_outputs(left_out.get_buffer(), right_out.get_buffer());
m_client.detach(); m_client.set_inputs(left_in.get_non_const_buffer(), right_in.get_non_const_buffer());
m_client.attach(clientname,opt);
left_out.allocate(buffer_size);
right_out.allocate(buffer_size);
left_in.allocate(buffer_size);
right_in.allocate(buffer_size);
m_samplerate = samplerate;
portaudio_client::device_options opt;
opt.buffer_size = buffer_size;
opt.num_buffers = 2;
opt.samplerate = samplerate;
opt.in_channels = 2;
opt.out_channels = 2;
m_client.set_outputs(left_out.get_buffer(), right_out.get_buffer());
m_client.set_inputs(left_in.get_non_const_buffer(), right_in.get_non_const_buffer());
m_client.attach(output_device_name,clientname,opt);
} }
void audio_device::save_sample(const string &filename, const sample s) { void audio_device::save_sample(const string &filename, const sample s) {
SF_INFO sfinfo; SF_INFO sfinfo;
sfinfo.format=SF_FORMAT_WAV | SF_FORMAT_FLOAT; sfinfo.format=SF_FORMAT_WAV | SF_FORMAT_FLOAT;
sfinfo.frames=s.get_length(); sfinfo.frames=s.get_length();
sfinfo.samplerate=m_samplerate; sfinfo.samplerate=44100;
sfinfo.channels=1; sfinfo.channels=1;
sfinfo.sections=1; sfinfo.sections=1;
sfinfo.seekable=0; sfinfo.seekable=0;
@ -91,4 +82,5 @@ void audio_device::maybe_record() {
} }
} }
void audio_device::start_graph(graph *graph) {
}

View File

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

View File

@ -19,16 +19,15 @@
#include "portaudio_client.h" #include "portaudio_client.h"
bool portaudio_client::m_attached = false;
long unsigned int portaudio_client::m_buffer_size = 0; long unsigned int portaudio_client::m_buffer_size = 0;
bool portaudio_client::m_initialised = false; long unsigned int portaudio_client::m_sample_rate = 44100;
int portaudio_client::m_attached_device = -1;
void (*portaudio_client::run_callback)(void*, unsigned int buf_size)=NULL; void (*portaudio_client::run_callback)(void*, unsigned int buf_size)=NULL;
void *portaudio_client::run_context = NULL; void *portaudio_client::run_context = NULL;
const float *portaudio_client::m_right_data=NULL; const float *portaudio_client::m_right_data=NULL;
const float *portaudio_client::m_left_data=NULL; const float *portaudio_client::m_left_data=NULL;
float *portaudio_client::m_right_in_data=NULL; float *portaudio_client::m_right_in_data=NULL;
float *portaudio_client::m_left_in_data=NULL; float *portaudio_client::m_left_in_data=NULL;
PaStream *portaudio_client::m_stream=NULL;
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
@ -41,103 +40,55 @@ portaudio_client::~portaudio_client() {
detach(); detach();
} }
bool portaudio_client::init() {
m_initialised=false;
if (!m_initialised) {
PaError err;
err = Pa_Initialize();
if( err != paNoError ) {
Pa_Terminate();
m_status="error initialising portaudio: "+string(Pa_GetErrorText(err))+"\n";
return false;
}
// load all the devices we have
PaDeviceIndex default_output_num = Pa_GetDefaultOutputDevice();
PaDeviceIndex default_input_num = Pa_GetDefaultInputDevice();
m_devices.clear();
// get all devices we have available
int numDevices = Pa_GetDeviceCount();
if(numDevices <= 0) {
m_status="portaudio error: no audio devices found";
return false;
}
const PaDeviceInfo *deviceInfo;
for(int i=0; i<numDevices; i++) {
deviceInfo = Pa_GetDeviceInfo(i);
if (deviceInfo->maxOutputChannels>=2) {
device_desc desc;
desc.name = deviceInfo->name;
desc.id = i;
desc.default_input = i==default_input_num;
desc.default_output = i==default_output_num;
m_devices.push_back(desc);
}
}
m_initialised=true;
return true;
}
return true;
}
int portaudio_client::device_name_to_id(const string &name) {
for (auto &d:m_devices) {
if (d.name==name) return d.id;
}
return -1;
}
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
bool portaudio_client::attach(const string &requested_output_device, const string &client_name, const device_options &dopt) { bool portaudio_client::attach(const string &client_name, const device_options &dopt) {
if (!init()) return false; if (m_attached) return true;
detach();
int requested_output_id = device_name_to_id(requested_output_device); PaError err;
err = Pa_Initialize();
PaStreamParameters output_parameters; if( err != paNoError ) {
if (requested_output_device=="" || requested_output_id==-1) { cerr<<"could not init portaudio_client"<<endl;
// start up by connecting to the default one Pa_Terminate();
PaDeviceIndex default_output_num = Pa_GetDefaultOutputDevice(); fprintf( stderr, "an error occured while using the portaudio stream\n" );
if (default_output_num == paNoDevice) { fprintf( stderr, "error number: %d\n", err );
m_status="error: no default output device."; fprintf( stderr, "error message: %s\n", Pa_GetErrorText( err ) );
return false;
} else {
output_parameters.device = default_output_num;
}
} else {
output_parameters.device = requested_output_id;
} }
output_parameters.channelCount = 2; /* stereo output */ PaDeviceIndex output_device_num = Pa_GetDefaultOutputDevice();
output_parameters.sampleFormat = paFloat32; /* 32 bit floating point output */ PaDeviceIndex input_device_num = Pa_GetDefaultInputDevice();
output_parameters.suggestedLatency = Pa_GetDeviceInfo( output_parameters.device )->defaultLowOutputLatency;
output_parameters.hostApiSpecificStreamInfo = NULL;
m_status="connecting to "+string(Pa_GetDeviceInfo(output_parameters.device)->name)+" for output\n";
// turn off input for the moment, it's causing PaStreamParameters output_parameters;
// too many cross platform security issues output_parameters.device = output_device_num;
if (output_parameters.device == paNoDevice) {
cerr<<"error: no default output device."<<endl;
} else {
output_parameters.channelCount = 2; /* stereo output */
output_parameters.sampleFormat = paFloat32; /* 32 bit floating point output */
output_parameters.suggestedLatency = Pa_GetDeviceInfo( output_parameters.device )->defaultLowOutputLatency;
output_parameters.hostApiSpecificStreamInfo = NULL;
cerr<<"Connecting to "<<Pa_GetDeviceInfo( output_parameters.device )->name<<" for output"<<endl;
}
/*PaStreamParameters input_parameters;
PaStreamParameters input_parameters;
PaStreamParameters *input_p=&input_parameters; PaStreamParameters *input_p=&input_parameters;
input_parameters.device = input_device_num; input_parameters.device = input_device_num;
if (true || input_parameters.device == paNoDevice) { if (true || input_parameters.device == paNoDevice) {
cerr<<"error: no default input device."<<endl; cerr<<"error: no default input device."<<endl;
input_p=0; input_p=0;
} else { } else {
input_parameters.channelCount = 2; input_parameters.channelCount = 2; /* stereo output */
input_parameters.sampleFormat = paFloat32; input_parameters.sampleFormat = paFloat32; /* 32 bit floating point output */
input_parameters.suggestedLatency = Pa_GetDeviceInfo( input_parameters.device )->defaultLowInputLatency; input_parameters.suggestedLatency = Pa_GetDeviceInfo( input_parameters.device )->defaultLowInputLatency;
input_parameters.hostApiSpecificStreamInfo = NULL; input_parameters.hostApiSpecificStreamInfo = NULL;
cerr<<"Connecting to "<<Pa_GetDeviceInfo( input_parameters.device )->name<<" for input"<<endl; cerr<<"Connecting to "<<Pa_GetDeviceInfo( input_parameters.device )->name<<" for input"<<endl;
} */ }
PaError err = Pa_OpenStream(&m_stream, PaStream *stream;
NULL,
err = Pa_OpenStream(&stream,
input_p,
&output_parameters, &output_parameters,
dopt.samplerate, dopt.samplerate,
dopt.buffer_size, dopt.buffer_size,
@ -145,38 +96,31 @@ bool portaudio_client::attach(const string &requested_output_device, const strin
process, process,
NULL); NULL);
m_attached_device=output_parameters.device;
if(err != paNoError) { if(err != paNoError) {
m_status+="could not attach: "+string(Pa_GetErrorText(err))+"\n"; cerr<<"could not attach portaudio_client: "<<Pa_GetErrorText( err )<<endl;
detach(); Pa_Terminate();
return false; return false;
} }
err = Pa_StartStream(m_stream); err = Pa_StartStream(stream);
if(err != paNoError) { if(err != paNoError) {
m_status+="could not start stream: "+string(Pa_GetErrorText(err))+"\n"; cerr<<"could not start stream: "<<Pa_GetErrorText( err )<<endl;
detach(); Pa_Terminate();
return false; return false;
} }
m_status+="we are connected to portaudio!\n"; m_attached=true;
cerr<<"connected to portaudio..."<<endl;
return true; return true;
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
void portaudio_client::detach() { void portaudio_client::detach() {
if (m_attached_device!=-1) { cerr<<"detaching from portaudio"<<endl;
if (m_stream!=NULL) { Pa_Terminate();
Pa_CloseStream(m_stream); m_attached=false;
}
m_stream=NULL;
m_status+="detaching from portaudio\n";
Pa_Terminate();
m_attached_device=-1;
}
} }
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -30,9 +30,9 @@ class portaudio_client
public: public:
portaudio_client(); portaudio_client();
~portaudio_client(); ~portaudio_client();
bool init();
class device_options { class device_options
{
public: public:
enum type {READ,WRITE,READWRITE}; enum type {READ,WRITE,READWRITE};
unsigned int buffer_size; unsigned int buffer_size;
@ -42,25 +42,13 @@ class portaudio_client
unsigned int out_channels; unsigned int out_channels;
}; };
class device_desc { bool attach(const string &client_name, const device_options &dopt);
public:
string name;
int id;
bool default_input;
bool default_output;
};
vector<portaudio_client::device_desc> m_devices;
bool attach(const string &requested_output_device, const string &client_name, const device_options &dopt);
void detach(); void detach();
bool is_attached() { return m_attached_device!=-1; } bool is_attached() { return m_attached; }
void set_callback(void(*run)(void*, unsigned int),void *context) { run_callback=run; run_context=context; } void set_callback(void(*run)(void*, unsigned int),void *context) { run_callback=run; run_context=context; }
void set_outputs(const float *l, const float *r) { m_left_data=l; m_right_data=r; } void set_outputs(const float *l, const float *r) { m_left_data=l; m_right_data=r; }
void set_inputs(float *l, float *r) { m_left_in_data=l; m_right_in_data=r; } void set_inputs(float *l, float *r) { m_left_in_data=l; m_right_in_data=r; }
string m_status;
protected: protected:
static int process(const void *input_buffer, void *output_buffer, static int process(const void *input_buffer, void *output_buffer,
@ -71,11 +59,9 @@ class portaudio_client
private: private:
int device_name_to_id(const string &name);
static long unsigned int m_buffer_size; static long unsigned int m_buffer_size;
static bool m_initialised; static long unsigned int m_sample_rate;
static int m_attached_device; static bool m_attached;
static const float *m_right_data; static const float *m_right_data;
static const float *m_left_data; static const float *m_left_data;
@ -84,8 +70,6 @@ class portaudio_client
static void(*run_callback)(void *, unsigned int); static void(*run_callback)(void *, unsigned int);
static void *run_context; static void *run_context;
static PaStream *m_stream;
}; };
#endif #endif

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,14 +24,11 @@ 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); static void sound_item_refresh();
static void sound_item_refresh(); static lo_address m_address;
static void add_audio_device(int id, const std::string &name, bool default_output);
static void audio_device_status(const std::string &status);
static lo_address m_address;
}; };
} }

View File

@ -1,72 +0,0 @@
# Building from source
## Linux (Ubuntu)
Install libraries for the sample engine (use brew on mac, MinGW on win):
$ sudo apt install libsndfile1-dev portaudio19-dev liblo-dev libfftw3-dev
Install dependencies for the interface:
$ 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:
$ mkdir build
$ cd build
$ qmake ..
$ make
$ sudo make install
$ samplebrain
## Mac
Install libraries for sample engine:
$ brew install fftw portaudio liblo libsndfile
Install dependencies for the interface:
$ brew install qt
$ brew link qt
Build & run it:
$ mkdir build
$ cd build
$ qmake ..
$ make
`samplebrain.app` should then be in the app folder for you to run.
# Mac build additions
To make a mac app bundle:
Run `macdeployqt` which copies all dependencies inside the app.
$ cd build
$ macdeployqt
If the icon is not visible, you might need to copy desktop/samplebrain.icns (the icon) to the Resources directory in the app bundle.
$ cp ../desktop/samplebrain.icns samplebrain.app/Contents/Resources
Then edit Info.plist to add samplebrain.icns to CFBundleIconFile. Key `CFBundleIconFile` should match:
<key>CFBundleIconFile</key>
<string>samplebrain.icns</string>
You might also need to resign the app bundle after making any changes
$ 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,36 +0,0 @@
# 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
* **Windows**: [samplebrain_0.18.3_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.3_win.zip)
* **Mac (intel/m1)**: [samplebrain_0.18.3_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.3_macintel.app.zip)
Changes: Release fixes loading samples from paths longer than 255 characters
0.18.2
* **Windows**: [samplebrain_0.18.2_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.2_win.zip)
Changes: Crash fix when closing load session file dialog
0.18.1
* **Windows**: [samplebrain_0.18.1_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.1_win.zip)
* **Mac (intel/m1)**: [samplebrain_0.18.1_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.1_macintel.app.zip)
Changes: Turned off microphone input to prevent security problems
0.18 (initial release)
* **Windows**: [samplebrain_0.18_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18_win.zip)
* **Mac (intel)**: [samplebrain_0.18_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18_macintel.zip)
* **Mac (m1)**: [samplebrain_0.18_m1_v2.dmg](https://static.thentrythis.org/samplebrain/samplebrain_0.18_m1_v2.dmg)

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.3</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">
@ -96,9 +96,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>plain fft match vs mfcc values </string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -159,9 +156,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>match original or normalised blocks</string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -304,9 +298,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>use new blocks rather than similar ones</string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -370,9 +361,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>how long it takes for the novelty to wear off</string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -415,7 +403,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>likelihood of playing the next block rather than the closest</string> <string>how long it takes for the novelty to wear off</string>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>100</number> <number>100</number>
@ -436,9 +424,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>likelihood of playing the next block rather than the closest</string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -506,7 +491,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>repeat search (set novelty to 0 for dodgy jungle timessssstretch)</string> <string>how many connections to search (ordered in closeness)</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>1</number> <number>1</number>
@ -681,7 +666,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>block difference higher than this causes a new search, skipping the target</string> <string>how many connections to search (ordered in closeness)</string>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>10000</number> <number>10000</number>
@ -728,13 +713,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">
@ -774,7 +752,7 @@
<number>99999</number> <number>99999</number>
</property> </property>
<property name="value"> <property name="value">
<number>1000</number> <number>3000</number>
</property> </property>
</widget> </widget>
</item> </item>
@ -805,7 +783,7 @@
<double>0.010000000000000</double> <double>0.010000000000000</double>
</property> </property>
<property name="value"> <property name="value">
<double>0.750000000000000</double> <double>0.800000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
@ -966,9 +944,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>amount to match the frequency</string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -1026,9 +1001,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>mix in the normalised blocks</string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -1089,9 +1061,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>mix in the original blocks</string>
</property>
<property name="maximum"> <property name="maximum">
<double>1.000000000000000</double> <double>1.000000000000000</double>
</property> </property>
@ -1119,8 +1088,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>
@ -1267,7 +1236,7 @@
<number>99999</number> <number>99999</number>
</property> </property>
<property name="value"> <property name="value">
<number>1000</number> <number>3000</number>
</property> </property>
</widget> </widget>
</item> </item>
@ -1298,7 +1267,7 @@
<double>0.010000000000000</double> <double>0.010000000000000</double>
</property> </property>
<property name="value"> <property name="value">
<double>0.750000000000000</double> <double>0.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
@ -1593,33 +1562,6 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="font">
<font>
<family>Comic Sans MS</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../app/samplebrain.qrc">
<normaloff>:/images/images/settings.png</normaloff>:/images/images/settings.png</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
@ -1651,6 +1593,8 @@
</widget> </widget>
<resources> <resources>
<include location="../app/samplebrain.qrc"/> <include location="../app/samplebrain.qrc"/>
<include location="../app/samplebrain.qrc"/>
<include location="../app/samplebrain.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>
@ -1660,8 +1604,8 @@
<slot>play_slot()</slot> <slot>play_slot()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>78</x> <x>64</x>
<y>830</y> <y>62</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1676,8 +1620,8 @@
<slot>stop_slot()</slot> <slot>stop_slot()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>180</x> <x>155</x>
<y>830</y> <y>62</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1692,8 +1636,8 @@
<slot>volume_slot(int)</slot> <slot>volume_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>465</x> <x>189</x>
<y>852</y> <y>480</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1708,8 +1652,8 @@
<slot>stop_record()</slot> <slot>stop_record()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>356</x> <x>328</x>
<y>840</y> <y>543</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1724,8 +1668,8 @@
<slot>record()</slot> <slot>record()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>268</x> <x>236</x>
<y>840</y> <y>543</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1740,8 +1684,8 @@
<slot>fft1_end_slot(int)</slot> <slot>fft1_end_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>154</x>
<y>293</y> <y>310</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1756,8 +1700,8 @@
<slot>ratio_slot(double)</slot> <slot>ratio_slot(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>109</x>
<y>185</y> <y>223</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1772,12 +1716,12 @@
<slot>setValue(int)</slot> <slot>setValue(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>319</x> <x>237</x>
<y>603</y> <y>289</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>421</x> <x>341</x>
<y>614</y> <y>289</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -1788,8 +1732,8 @@
<slot>target_mix_slot(double)</slot> <slot>target_mix_slot(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>720</x> <x>330</x>
<y>669</y> <y>446</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1804,8 +1748,8 @@
<slot>generate_target_blocks()</slot> <slot>generate_target_blocks()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>670</x> <x>277</x>
<y>395</y> <y>202</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1820,8 +1764,8 @@
<slot>target_block_size(int)</slot> <slot>target_block_size(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>720</x> <x>313</x>
<y>237</y> <y>136</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1836,8 +1780,8 @@
<slot>load_target()</slot> <slot>load_target()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>670</x> <x>277</x>
<y>184</y> <y>103</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1852,8 +1796,8 @@
<slot>fft1_start_slot(int)</slot> <slot>fft1_start_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>298</x> <x>154</x>
<y>293</y> <y>277</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>399</x> <x>399</x>
@ -1868,8 +1812,8 @@
<slot>target_block_overlap(double)</slot> <slot>target_block_overlap(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>720</x> <x>619</x>
<y>291</y> <y>196</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1884,12 +1828,12 @@
<slot>setValue(int)</slot> <slot>setValue(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>341</x>
<y>614</y> <y>289</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>319</x> <x>237</x>
<y>603</y> <y>289</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -1900,8 +1844,8 @@
<slot>synapses(int)</slot> <slot>synapses(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>341</x>
<y>614</y> <y>289</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -1916,8 +1860,8 @@
<slot>ratio_slot(int)</slot> <slot>ratio_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>323</x> <x>189</x>
<y>174</y> <y>141</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1932,8 +1876,8 @@
<slot>n_ratio_slot(int)</slot> <slot>n_ratio_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>323</x> <x>159</x>
<y>228</y> <y>211</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1948,8 +1892,8 @@
<slot>n_ratio_slot(double)</slot> <slot>n_ratio_slot(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>330</x>
<y>239</y> <y>211</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1964,8 +1908,8 @@
<slot>target_mix_slot(int)</slot> <slot>target_mix_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>622</x> <x>159</x>
<y>658</y> <y>446</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1980,8 +1924,8 @@
<slot>n_mix_slot(int)</slot> <slot>n_mix_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>622</x> <x>159</x>
<y>604</y> <y>386</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -1996,8 +1940,8 @@
<slot>n_mix_slot(double)</slot> <slot>n_mix_slot(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>720</x> <x>330</x>
<y>615</y> <y>386</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>361</x> <x>361</x>
@ -2012,8 +1956,8 @@
<slot>load_brain()</slot> <slot>load_brain()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>941</x> <x>615</x>
<y>661</y> <y>357</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2028,8 +1972,8 @@
<slot>boredom_slot(double)</slot> <slot>boredom_slot(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>411</x>
<y>401</y> <y>253</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>321</x> <x>321</x>
@ -2044,8 +1988,8 @@
<slot>novelty_slot(double)</slot> <slot>novelty_slot(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>411</x>
<y>347</y> <y>217</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>321</x> <x>321</x>
@ -2060,8 +2004,8 @@
<slot>novelty_slot(int)</slot> <slot>novelty_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>323</x> <x>291</x>
<y>336</y> <y>217</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>321</x> <x>321</x>
@ -2076,8 +2020,8 @@
<slot>boredom_slot(int)</slot> <slot>boredom_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>323</x> <x>291</x>
<y>390</y> <y>253</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>321</x> <x>321</x>
@ -2092,8 +2036,8 @@
<slot>synapses(int)</slot> <slot>synapses(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>319</x> <x>237</x>
<y>603</y> <y>289</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2108,8 +2052,8 @@
<slot>block_size(int)</slot> <slot>block_size(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1157</x> <x>728</x>
<y>450</y> <y>109</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2124,8 +2068,8 @@
<slot>block_overlap(double)</slot> <slot>block_overlap(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1157</x> <x>728</x>
<y>504</y> <y>145</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2140,8 +2084,8 @@
<slot>save_brain()</slot> <slot>save_brain()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1157</x> <x>728</x>
<y>661</y> <y>357</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2156,8 +2100,8 @@
<slot>clear_brain()</slot> <slot>clear_brain()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1157</x> <x>1061</x>
<y>396</y> <y>550</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2172,8 +2116,8 @@
<slot>generate()</slot> <slot>generate()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1158</x> <x>671</x>
<y>608</y> <y>322</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2188,8 +2132,8 @@
<slot>load_sound()</slot> <slot>load_sound()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>868</x> <x>841</x>
<y>396</y> <y>550</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2204,12 +2148,12 @@
<slot>setValue(int)</slot> <slot>setValue(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>346</x> <x>241</x>
<y>498</y> <y>282</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>421</x> <x>343</x>
<y>509</y> <y>282</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -2220,12 +2164,12 @@
<slot>setValue(int)</slot> <slot>setValue(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>343</x>
<y>509</y> <y>282</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>346</x> <x>241</x>
<y>498</y> <y>282</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -2236,8 +2180,8 @@
<slot>search_stretch(int)</slot> <slot>search_stretch(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>346</x> <x>241</x>
<y>498</y> <y>282</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2252,12 +2196,12 @@
<slot>setValue(int)</slot> <slot>setValue(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>305</x> <x>231</x>
<y>657</y> <y>410</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>421</x> <x>337</x>
<y>668</y> <y>410</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -2268,12 +2212,12 @@
<slot>setValue(int)</slot> <slot>setValue(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>337</x>
<y>668</y> <y>410</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>305</x> <x>231</x>
<y>657</y> <y>410</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>
@ -2284,8 +2228,8 @@
<slot>slide_error(int)</slot> <slot>slide_error(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>305</x> <x>231</x>
<y>657</y> <y>410</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>566</x> <x>566</x>
@ -2300,8 +2244,8 @@
<slot>stickyness_slot(double)</slot> <slot>stickyness_slot(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>385</x>
<y>455</y> <y>296</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>609</x> <x>609</x>
@ -2316,8 +2260,8 @@
<slot>stickyness_slot(int)</slot> <slot>stickyness_slot(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>323</x> <x>266</x>
<y>444</y> <y>296</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>609</x> <x>609</x>
@ -2332,8 +2276,8 @@
<slot>autotune(int)</slot> <slot>autotune(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>622</x> <x>531</x>
<y>550</y> <y>477</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2348,8 +2292,8 @@
<slot>autotune(double)</slot> <slot>autotune(double)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>720</x> <x>616</x>
<y>561</y> <y>477</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2364,8 +2308,8 @@
<slot>load_session()</slot> <slot>load_session()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>616</x> <x>535</x>
<y>799</y> <y>707</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2380,8 +2324,8 @@
<slot>save_session()</slot> <slot>save_session()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>616</x> <x>535</x>
<y>851</y> <y>744</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2396,8 +2340,8 @@
<slot>stereo_mode(bool)</slot> <slot>stereo_mode(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>721</x> <x>539</x>
<y>717</y> <y>594</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2412,8 +2356,8 @@
<slot>algo(int)</slot> <slot>algo(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>421</x> <x>273</x>
<y>560</y> <y>395</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2428,8 +2372,8 @@
<slot>target_shape(int)</slot> <slot>target_shape(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>720</x> <x>557</x>
<y>342</y> <y>233</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2444,8 +2388,8 @@
<slot>brain_shape(int)</slot> <slot>brain_shape(int)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1157</x> <x>824</x>
<y>555</y> <y>432</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2460,8 +2404,8 @@
<slot>load_sounds()</slot> <slot>load_sounds()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1013</x> <x>754</x>
<y>396</y> <y>321</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2476,8 +2420,8 @@
<slot>select_all()</slot> <slot>select_all()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1073</x> <x>813</x>
<y>124</y> <y>74</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2492,8 +2436,8 @@
<slot>select_none()</slot> <slot>select_none()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>1157</x> <x>862</x>
<y>124</y> <y>74</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2508,8 +2452,8 @@
<slot>mic(bool)</slot> <slot>mic(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>721</x> <x>404</x>
<y>442</y> <y>601</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>454</x> <x>454</x>
@ -2517,22 +2461,6 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>pushButton</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>settings()</slot>
<hints>
<hint type="sourcelabel">
<x>680</x>
<y>809</y>
</hint>
<hint type="destinationlabel">
<x>776</x>
<y>849</y>
</hint>
</hints>
</connection>
</connections> </connections>
<slots> <slots>
<slot>play_slot()</slot> <slot>play_slot()</slot>
@ -2590,6 +2518,5 @@
<slot>select_all()</slot> <slot>select_all()</slot>
<slot>select_none()</slot> <slot>select_none()</slot>
<slot>mic(bool)</slot> <slot>mic(bool)</slot>
<slot>settings()</slot>
</slots> </slots>
</ui> </ui>

View File

@ -1,490 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsDialog</class>
<widget class="QDialog" name="SettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>438</width>
<height>656</height>
</rect>
</property>
<property name="windowTitle">
<string>settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>device</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="deviceComboBox">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>sample rate</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="samplerateLineEdit">
<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>
<property name="text">
<string>44100</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>8</pointsize>
</font>
</property>
<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>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>buffer size</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="buffersizeComboBox">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="currentIndex">
<number>5</number>
</property>
<item>
<property name="text">
<string>64</string>
</property>
</item>
<item>
<property name="text">
<string>128</string>
</property>
</item>
<item>
<property name="text">
<string>256</string>
</property>
</item>
<item>
<property name="text">
<string>512</string>
</property>
</item>
<item>
<property name="text">
<string>1024</string>
</property>
</item>
<item>
<property name="text">
<string>2048</string>
</property>
</item>
<item>
<property name="text">
<string>4096</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>messages</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="messagesLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">border: 1px solid;</string>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</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>
<widget class="QPushButton" name="applyPushButton">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="text">
<string>apply settings</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="font">
<font>
<family>Comic Sans MS</family>
</font>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>244</x>
<y>642</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>312</x>
<y>642</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>samplerateLineEdit</sender>
<signal>textEdited(QString)</signal>
<receiver>SettingsDialog</receiver>
<slot>samplerate(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>270</x>
<y>71</y>
</hint>
<hint type="destinationlabel">
<x>394</x>
<y>156</y>
</hint>
</hints>
</connection>
<connection>
<sender>applyPushButton</sender>
<signal>clicked()</signal>
<receiver>SettingsDialog</receiver>
<slot>apply()</slot>
<hints>
<hint type="sourcelabel">
<x>125</x>
<y>592</y>
</hint>
<hint type="destinationlabel">
<x>4</x>
<y>315</y>
</hint>
</hints>
</connection>
<connection>
<sender>deviceComboBox</sender>
<signal>currentTextChanged(QString)</signal>
<receiver>SettingsDialog</receiver>
<slot>output_device(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>323</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>393</x>
<y>64</y>
</hint>
</hints>
</connection>
<connection>
<sender>buffersizeComboBox</sender>
<signal>currentTextChanged(QString)</signal>
<receiver>SettingsDialog</receiver>
<slot>buffersize(QString)</slot>
<hints>
<hint type="sourcelabel">
<x>390</x>
<y>215</y>
</hint>
<hint type="destinationlabel">
<x>395</x>
<y>208</y>
</hint>
</hints>
</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>
<slots>
<slot>output_device(QString)</slot>
<slot>samplerate(QString)</slot>
<slot>buffersize(QString)</slot>
<slot>apply()</slot>
<slot>gui_port(QString)</slot>
<slot>audio_port(QString)</slot>
<slot>process_port(QString)</slot>
</slots>
</ui>

View File

@ -10,14 +10,11 @@ INCLUDEPATH += . 2
QT += core gui widgets QT += core gui widgets
# Input # Input
HEADERS += app/MainWindow.h \ HEADERS += app/MainWindow.h
app/SettingsDialog.h
FORMS += gui/samplebrain.ui \ FORMS += gui/samplebrain.ui
gui/settings.ui
SOURCES += app/MainWindow.cpp \ SOURCES += app/MainWindow.cpp \
app/SettingsDialog.cpp \
app/sound_items.cpp \ app/sound_items.cpp \
app/audio_thread.cpp \ app/audio_thread.cpp \
app/process_thread.cpp \ app/process_thread.cpp \