mirror of
https://gitlab.com/then-try-this/samplebrain.git
synced 2025-05-12 18:47:21 +00:00
Merge remote-tracking branch 'origin/development' into main
This commit is contained in:
commit
65ea2080be
18
README.md
18
README.md
@ -34,6 +34,10 @@ 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/).
|
||||||
|
|
||||||
|
# Community
|
||||||
|
|
||||||
|
* https://www.reddit.com/r/samplebrain/
|
||||||
|
|
||||||
# Download
|
# Download
|
||||||
|
|
||||||
As this is experimental non-commercial software (only originally
|
As this is experimental non-commercial software (only originally
|
||||||
@ -41,12 +45,16 @@ 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.4_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_win.zip)
|
* **Windows**: [samplebrain_0.18.5_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.5_win.zip)
|
||||||
* **Mac (intel/m1)**: [samplebrain_0.18.4_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_macintel.app.zip)
|
* **Mac (intel/m1)**: [samplebrain_0.18.5_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.5_macintel.app.zip)
|
||||||
|
|
||||||
Changes in 0.18.4: New audio device settings window and updated
|
Changes in 0.18.5 (relased 28/10/22):
|
||||||
windows build. Better default block size, tool tip tweaks and fixes
|
|
||||||
for dark themes by [Claude Heiland-Allen](https://mathr.co.uk/).
|
* 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)
|
For old versions see the [changelog](changelog.md)
|
||||||
|
|
||||||
|
@ -28,7 +28,11 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
MainWindow::MainWindow(const string &port, const string &audio_port, const string &process_port, QSettings *settings) :
|
MainWindow::MainWindow(const string &port, const string &audio_port, const string &process_port, QSettings *settings) :
|
||||||
m_last_file("."),
|
m_last_sound_file("."),
|
||||||
|
m_last_target_file("."),
|
||||||
|
m_last_brain_file("."),
|
||||||
|
m_last_session_file("."),
|
||||||
|
m_last_recording_file("."),
|
||||||
m_feedback(port),
|
m_feedback(port),
|
||||||
m_audio_port(audio_port),
|
m_audio_port(audio_port),
|
||||||
m_process_port(process_port),
|
m_process_port(process_port),
|
||||||
@ -157,6 +161,12 @@ 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());
|
||||||
|
|
||||||
|
141
app/MainWindow.h
141
app/MainWindow.h
@ -206,12 +206,15 @@ private slots:
|
|||||||
|
|
||||||
void run_slot() {}
|
void run_slot() {}
|
||||||
void load_target() {
|
void load_target() {
|
||||||
m_last_file=QFileDialog::getOpenFileName(this,
|
QString path=QFileDialog::getOpenFileName(this,
|
||||||
QString("Select an audio file"),
|
QString("Select an audio file"),
|
||||||
m_last_file,
|
m_last_target_file,
|
||||||
m_format_string);
|
m_format_string);
|
||||||
|
if (m_last_target_file!="") {
|
||||||
send_process_osc("/load_target","s",m_last_file.toStdString().c_str());
|
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 target_block_size(int s) { send_process_osc("/target_block_size","i",s); }
|
void target_block_size(int s) { send_process_osc("/target_block_size","i",s); }
|
||||||
void target_block_overlap(double s) { send_process_osc("/target_overlap","f",s); }
|
void target_block_overlap(double s) { send_process_osc("/target_overlap","f",s); }
|
||||||
@ -221,14 +224,15 @@ private slots:
|
|||||||
void fft_spectrum_size(int) {}
|
void fft_spectrum_size(int) {}
|
||||||
void generate() { send_process_osc("/generate_brain",""); }
|
void generate() { send_process_osc("/generate_brain",""); }
|
||||||
void load_sound() {
|
void load_sound() {
|
||||||
m_last_file=QFileDialog::getOpenFileName(this,
|
QString path=QFileDialog::getOpenFileName(this,
|
||||||
QString("Select a wav file"),
|
QString("Select a wav file"),
|
||||||
m_last_file,
|
m_last_sound_file,
|
||||||
m_format_string);
|
m_format_string);
|
||||||
|
|
||||||
if (m_last_file!="") {
|
if (path!="") {
|
||||||
send_process_osc("/load_sample","s",m_last_file.toStdString().c_str());
|
m_last_sound_file=path;
|
||||||
sound_items::sound_item &si = m_sound_items.add(m_Ui.brain_contents, m_last_file.toStdString(),true);
|
send_process_osc("/load_sample","s",m_last_sound_file.toStdString().c_str());
|
||||||
|
sound_items::sound_item &si = m_sound_items.add(m_Ui.brain_contents, m_last_sound_file.toStdString(),true);
|
||||||
QObject::connect(si.m_enable, SIGNAL(clicked()), m_sound_item_enable_mapper, SLOT(map()));
|
QObject::connect(si.m_enable, SIGNAL(clicked()), m_sound_item_enable_mapper, SLOT(map()));
|
||||||
m_sound_item_enable_mapper->setMapping(si.m_enable, si.m_id);
|
m_sound_item_enable_mapper->setMapping(si.m_enable, si.m_id);
|
||||||
QObject::connect(si.m_del, SIGNAL(clicked()), m_sound_item_delete_mapper, SLOT(map()));
|
QObject::connect(si.m_del, SIGNAL(clicked()), m_sound_item_delete_mapper, SLOT(map()));
|
||||||
@ -238,25 +242,27 @@ private slots:
|
|||||||
|
|
||||||
|
|
||||||
void load_sounds() {
|
void load_sounds() {
|
||||||
m_last_file=QFileDialog::getExistingDirectory(this,
|
QString path=QFileDialog::getExistingDirectory(this,
|
||||||
QString("Select a directory of wav files"),
|
QString("Select a directory of wav files"),
|
||||||
m_last_file);
|
m_last_directory_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());
|
||||||
|
|
||||||
QDirIterator dirIt(m_last_file,QDirIterator::Subdirectories);
|
sound_items::sound_item &si = m_sound_items.add(m_Ui.brain_contents, dirIt.filePath().toStdString(),true);
|
||||||
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);
|
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_enable, SIGNAL(clicked()), m_sound_item_enable_mapper, SLOT(map()));
|
QObject::connect(si.m_del, SIGNAL(clicked()), m_sound_item_delete_mapper, SLOT(map()));
|
||||||
m_sound_item_enable_mapper->setMapping(si.m_enable, si.m_id);
|
m_sound_item_delete_mapper->setMapping(si.m_del, 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);
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,12 +319,11 @@ private slots:
|
|||||||
|
|
||||||
void record() {
|
void record() {
|
||||||
if (m_save_wav=="") {
|
if (m_save_wav=="") {
|
||||||
m_last_file=QFileDialog::getSaveFileName(
|
m_last_recording_file=QFileDialog::getSaveFileName(this,
|
||||||
this,
|
QString("Select a wav file"),
|
||||||
QString("Select a wav file"),
|
m_last_recording_file,
|
||||||
m_last_file,
|
QString("Sounds (*.wav);;All files (*.*)"));
|
||||||
QString("Sounds (*.wav);;All files (*.*)"));
|
m_save_wav = m_last_recording_file.toStdString();
|
||||||
m_save_wav = m_last_file.toStdString();
|
|
||||||
// chop off .wav
|
// chop off .wav
|
||||||
size_t pos = m_save_wav.find_last_of(".");
|
size_t pos = m_save_wav.find_last_of(".");
|
||||||
if (pos!=string::npos) {
|
if (pos!=string::npos) {
|
||||||
@ -339,43 +344,48 @@ private slots:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void load_brain() {
|
void load_brain() {
|
||||||
m_last_file=QFileDialog::getOpenFileName(
|
QString path=QFileDialog::getOpenFileName(this,
|
||||||
this,
|
QString("Select a brain file"),
|
||||||
QString("Select a brain file"),
|
m_last_brain_file,
|
||||||
m_last_file,
|
QString("Brains (*.brain);;All files (*.*)"));
|
||||||
QString("Brains (*.brain);;All files (*.*)"));
|
|
||||||
|
|
||||||
send_process_osc("/load_brain","s",m_last_file.toStdString().c_str());
|
if (path!="") {
|
||||||
|
m_last_brain_file=path;
|
||||||
|
send_process_osc("/load_brain","s",m_last_brain_file.toStdString().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void save_brain() {
|
void save_brain() {
|
||||||
m_last_file=QFileDialog::getSaveFileName(
|
QString path=QFileDialog::getSaveFileName(this,
|
||||||
this,
|
QString("Select a brain file"),
|
||||||
QString("Select a brain file"),
|
m_last_brain_file,
|
||||||
m_last_file,
|
QString("Brains (*.brain);;All files (*.*)"));
|
||||||
QString("Brains (*.brain);;All files (*.*)"));
|
if (path!="") {
|
||||||
|
m_last_brain_file=path;
|
||||||
send_process_osc("/save_brain","s",m_last_file.toStdString().c_str());
|
send_process_osc("/save_brain","s",m_last_brain_file.toStdString().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_session() {
|
void load_session() {
|
||||||
m_last_file=QFileDialog::getOpenFileName(
|
QString path=QFileDialog::getOpenFileName(this,
|
||||||
this,
|
QString("Select a session file"),
|
||||||
QString("Select a session file"),
|
m_last_session_file,
|
||||||
m_last_file,
|
QString("Sessions *.samplebrain (*.samplebrain);;All files (*.*)"));
|
||||||
QString("Sessions *.samplebrain (*.samplebrain);;All files (*.*)"));
|
if (path!="") {
|
||||||
|
m_last_session_file=path;
|
||||||
send_process_osc("/load_session","s",m_last_file.toStdString().c_str());
|
send_process_osc("/load_session","s",m_last_session_file.toStdString().c_str());
|
||||||
init_from_session(m_last_file.toStdString());
|
init_from_session(m_last_session_file.toStdString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_session() {
|
void save_session() {
|
||||||
m_last_file=QFileDialog::getSaveFileName(
|
QString path=QFileDialog::getSaveFileName(this,
|
||||||
this,
|
QString("Select a session file"),
|
||||||
QString("Select a session file"),
|
m_last_session_file,
|
||||||
m_last_file,
|
QString("Sessions *.samplebrain (*.samplebrain)"));
|
||||||
QString("Sessions *.samplebrain (*.samplebrain)"));
|
if (path!="") {
|
||||||
|
m_last_session_file=path;
|
||||||
send_process_osc("/save_session","s",m_last_file.toStdString().c_str());
|
send_process_osc("/save_session","s",m_last_session_file.toStdString().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_status() {
|
void update_status() {
|
||||||
@ -440,7 +450,12 @@ private:
|
|||||||
QSignalMapper* enable_mapper);
|
QSignalMapper* enable_mapper);
|
||||||
|
|
||||||
string m_save_wav;
|
string m_save_wav;
|
||||||
QString m_last_file;
|
QString m_last_sound_file;
|
||||||
|
QString m_last_target_file;
|
||||||
|
QString m_last_directory_file;
|
||||||
|
QString m_last_brain_file;
|
||||||
|
QString m_last_session_file;
|
||||||
|
QString m_last_recording_file;
|
||||||
unsigned int m_record_id;
|
unsigned int m_record_id;
|
||||||
Ui_MainWindow m_Ui;
|
Ui_MainWindow m_Ui;
|
||||||
feedback m_feedback;
|
feedback m_feedback;
|
||||||
|
@ -728,6 +728,13 @@
|
|||||||
</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">
|
||||||
@ -1112,8 +1119,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>20</width>
|
<width>17</width>
|
||||||
<height>40</height>
|
<height>13</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
|
@ -112,6 +112,7 @@ 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]));
|
||||||
|
@ -79,6 +79,7 @@ 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));
|
||||||
|
@ -228,6 +228,7 @@ u32 brain::rev_search(const block &target, const search_params ¶ms) {
|
|||||||
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 ¶ms) {
|
double brain::calc_average_diff(search_params ¶ms) {
|
||||||
double diff=0;
|
double diff=0;
|
||||||
@ -261,6 +262,7 @@ void brain::build_synapses_thresh(search_params ¶ms, double thresh) {
|
|||||||
++outer_index;
|
++outer_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void brain::build_synapses_fixed(search_params ¶ms) {
|
void brain::build_synapses_fixed(search_params ¶ms) {
|
||||||
//m_average_error = calc_average_diff(params)*thresh;
|
//m_average_error = calc_average_diff(params)*thresh;
|
||||||
|
@ -62,8 +62,8 @@ public:
|
|||||||
u32 rev_search(const block &target, const search_params ¶ms);
|
u32 rev_search(const block &target, const search_params ¶ms);
|
||||||
|
|
||||||
// synaptic search
|
// synaptic search
|
||||||
double calc_average_diff(search_params ¶ms);
|
// double calc_average_diff(search_params ¶ms);
|
||||||
void build_synapses_thresh(search_params ¶ms, double threshold);
|
// void build_synapses_thresh(search_params ¶ms, double threshold);
|
||||||
void build_synapses_fixed(search_params ¶ms);
|
void build_synapses_fixed(search_params ¶ms);
|
||||||
u32 search_synapses(const block &target, search_params ¶ms);
|
u32 search_synapses(const block &target, search_params ¶ms);
|
||||||
double get_current_error() { return m_current_error; }
|
double get_current_error() { return m_current_error; }
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
# Changlog
|
# Changlog
|
||||||
|
|
||||||
|
0.18.4
|
||||||
|
|
||||||
|
* **Windows**: [samplebrain_0.18.4_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_win.zip)
|
||||||
|
* **Mac (intel/m1)**: [samplebrain_0.18.4_macintel.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.4_macintel.app.zip)
|
||||||
|
|
||||||
|
Changes in 0.18.4: New audio device settings window and updated
|
||||||
|
windows build. Better default block size, tool tip tweaks and fixes
|
||||||
|
for dark themes by [Claude Heiland-Allen](https://mathr.co.uk/).
|
||||||
|
|
||||||
0.18.3
|
0.18.3
|
||||||
|
|
||||||
* **Windows**: [samplebrain_0.18.3_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.3_win.zip)
|
* **Windows**: [samplebrain_0.18.3_win.zip](https://static.thentrythis.org/samplebrain/samplebrain_0.18.3_win.zip)
|
||||||
|
11
debian/changelog
vendored
11
debian/changelog
vendored
@ -1,6 +1,11 @@
|
|||||||
samplebrain (0.18rc2-1ubuntu0~bionic4) bionic; urgency=medium
|
samplebrain (0.18.5rc1-1ubuntu0~bionic1) bionic; urgency=medium
|
||||||
|
|
||||||
* Initial release
|
* 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
|
||||||
|
|
||||||
|
-- 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
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user