37 Commits

Author SHA1 Message Date
8449f710fb Merge branch 'pr1' into 'main'
Little housekeeping

See merge request then-try-this/samplebrain!15
2022-10-31 18:36:00 +00:00
69dc3721be trying to set the path again for qt/windows ci build 2022-10-31 10:07:23 +00:00
f057cc6159 Use CMAKE_AUTORCC 2022-10-31 12:55:21 +03:00
33bba6d337 Extend .gitignore 2022-10-31 12:55:10 +03:00
16d04c8faf trying to set the path again for qt/windows ci build 2022-10-31 09:52:49 +00:00
994d002796 trying to set the patch for qt/windows ci build 2022-10-31 09:39:18 +00:00
0ab061eb0e back to qt5 again to attempt win ci to work (choco doesn't seem to have qt6 yet) 2022-10-30 18:37:28 +00:00
5573355c8e trying win ci - adding python 2022-10-30 12:01:38 +00:00
07fa73ecab trying win ci 2022-10-30 11:45:04 +00:00
5566284cd8 trying win ci 2022-10-30 11:40:15 +00:00
b0454ed2f4 trying win ci 2022-10-30 11:33:47 +00:00
e22a501aa7 trying removing deps 2022-10-30 11:24:46 +00:00
7a02dcfa3c switched (back) to qt6 2022-10-29 13:49:15 +01:00
b983408bd7 Merge branch 'samplebrain-parallel-synapse-generation' into main 2022-10-29 13:14:34 +01:00
fa44d2b4c7 added openmp to cmake 2022-10-29 13:13:16 +01:00
8e7a9abe1a removed pro file 2022-10-29 13:00:53 +01:00
65ea2080be Merge remote-tracking branch 'origin/development' into main 2022-10-29 12:53:34 +01:00
884c8ad91f resources location 2022-10-20 21:12:58 +01:00
1d03e9addd ci tweak 2022-10-14 22:33:17 +01:00
af44ac43f0 more cmake qt fiddling 2022-10-14 22:29:25 +01:00
b971435101 cmake qt fiddling 2022-10-14 22:25:38 +01:00
7bc12ac0be cmake build fixes 2022-10-14 22:18:52 +01:00
8038fdd9c2 Merge branch 'upgrade-to-cmake' into 'main'
Upgrade build system from qmake to cmake

See merge request then-try-this/samplebrain!11
2022-10-14 20:34:17 +00:00
bbdcd4b29c Merge branch 'main' into 'upgrade-to-cmake'
# Conflicts:
#   app/MainWindow.h
#   app/SettingsDialog.h
2022-10-14 20:31:07 +00:00
cf06a21160 Add Gitlab CI script 2022-10-12 15:22:37 +02:00
6471b1e066 Clean up CMakeLists
- Remove redundant libraries
- Change compile definitions to CMake variables
2022-10-12 15:21:51 +02:00
7d7a7d24a2 Remove Qt .pro file
CMakeLists.txt now does everything we need
2022-10-12 14:56:16 +02:00
2c1a3692e7 Update building.md
- Add info about installing cmake
- Change build instructions from qmake to cmake
- Remove info about installing deps
  We don't need to do this anymore. CMake will do it automatically at
  configure-time!
2022-10-12 14:56:16 +02:00
30e16d80d9 Add libsndfile dependency 2022-10-12 14:56:16 +02:00
2743caa02a Add portaudio dependency 2022-10-12 14:56:16 +02:00
572d6a127c Add liblo dependency 2022-10-12 14:56:16 +02:00
6aa25397de Add fftw3 dependency 2022-10-12 14:56:16 +02:00
55e5427ec4 Fix path to .ui files 2022-10-12 14:56:16 +02:00
c2e923bcee Ignore build folder
This should cover all files generated by the build system...
2022-10-12 14:56:16 +02:00
ddf7f8538a Fix CMakeLists syntax
target_compile_options requires the PUBLIC/PRIVATE keyword. I don't know
why the qmake2cmake script doesn't provide the correct syntax here...
2022-10-12 14:56:16 +02:00
1dc55a982c Run qmake2cmake command
Command used:
qmake2cmake_all . --min-qt-version 6.2.4
2022-10-12 14:56:07 +02:00
8aa0dee3d1 parallelize synapse generation using OpenMP
- only tested on Debian Linux with a 16-thread amd64 CPU
- Windows may need DLLs to be shipped with the EXE
- using `-fopenmp` should be made optional via qmake somehow
  (without the flag, parallelization pragmas are ignored
  and it reverts to serial operation)
- assumes `status::update()` among other code is thread-safe,
  it seems to work on my machine without issues...
2022-09-27 13:19:04 +01:00
16 changed files with 202 additions and 106 deletions

6
.gitignore vendored
View File

@ -1,3 +1,7 @@
*.rej
*.orig
.DS_Store
*.ini
build
*.*~ *.*~
*.o *.o

24
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,24 @@
build-ubuntu:
stage: build
image: ubuntu:22.04
script:
- apt-get update
- apt-get install -y git cmake g++ freeglut3-dev qtbase5-dev qt5-qmake qtbase5-dev-tools
- mkdir -p build
- cd build
- cmake ..
- cmake --build . --target samplebrain
build-win64:
tags:
- "windows"
before_script:
- choco install -y cmake python qt5-default
- $env:Path += ';C:\Program Files\CMake\bin'
stage: build
script:
- set CMAKE_PREFIX_PATH=C:\Qt\5.15.2\mingw81_64
- mkdir build
- cd build
- cmake ..
- cmake --build . --target samplebrain

81
CMakeLists.txt Normal file
View File

@ -0,0 +1,81 @@
cmake_minimum_required(VERSION 3.16)
project(samplebrain VERSION 1.0 LANGUAGES C CXX)
include(Dependencies.cmake)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Set up AUTOMOC and some sensible defaults for runtime execution
# When using Qt 6.3, you can replace the code block below with
# qt_standard_project_setup()
set(CMAKE_AUTOMOC ON)
include(GNUInstallDirs)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Gui Widgets)
find_package(OpenMP)
add_executable(samplebrain WIN32 MACOSX_BUNDLE
app/MainWindow.cpp app/MainWindow.h
app/SettingsDialog.cpp app/SettingsDialog.h
app/audio_thread.cpp
app/feedback.cpp
app/process_thread.cpp
app/qtmain.cpp
app/samplebrain.qrc
app/sound_items.cpp
brain/src/aquila/filter/MelFilter.cpp
brain/src/aquila/filter/MelFilterBank.cpp
brain/src/aquila/transform/Dct.cpp
brain/src/block.cpp
brain/src/block_stream.cpp
brain/src/brain.cpp
brain/src/fft.cpp
brain/src/mfcc.cpp
brain/src/renderer.cpp
brain/src/search_params.cpp
brain/src/spiralcore/OSC_server.cpp
brain/src/spiralcore/allocator.cpp
brain/src/spiralcore/audio.cpp
brain/src/spiralcore/command_ring_buffer.cpp
brain/src/spiralcore/portaudio_client.cpp
brain/src/spiralcore/ring_buffer.cpp
brain/src/spiralcore/sample.cpp
brain/src/spiralcore/stream.cpp
brain/src/status.cpp
brain/src/window.cpp
app/gui/samplebrain.ui
app/gui/settings.ui
)
target_include_directories(samplebrain PRIVATE
.
brain/src
)
target_link_libraries(samplebrain PRIVATE
Qt5::Core
Qt5::Gui
Qt5::Widgets
fftw3
lo_shared
portaudio
sndfile
)
if(OpenMP_CXX_FOUND)
target_link_libraries(samplebrain PUBLIC OpenMP::OpenMP_CXX)
endif()
install(TARGETS samplebrain
BUNDLE DESTINATION .
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
# Consider using qt_generate_deploy_app_script() for app deployment if
# the project can use Qt 6.3. In that case rerun qmake2cmake with
# --min-qt-version=6.3.

49
Dependencies.cmake Normal file
View File

@ -0,0 +1,49 @@
################################################################################
# FetchContent
################################################################################
include(FetchContent)
################################################################################
# fftw3
################################################################################
FetchContent_Declare(
fftw3
URL http://fftw.org/fftw-3.3.10.tar.gz
URL_HASH MD5=8ccbf6a5ea78a16dbc3e1306e234cc5c)
FetchContent_MakeAvailable(fftw3)
include_directories(${fftw3_SOURCE_DIR}/api)
################################################################################
# liblo
################################################################################
FetchContent_Declare(
liblo
URL http://downloads.sourceforge.net/liblo/liblo-0.31.tar.gz
URL_HASH MD5=14378c1e74c58e777fbb4fcf33ac5315)
FetchContent_MakeAvailable(liblo)
add_subdirectory(${liblo_SOURCE_DIR}/cmake)
################################################################################
# PortAudio
################################################################################
FetchContent_Declare(
portaudio
URL http://files.portaudio.com/archives/pa_stable_v190700_20210406.tgz
URL_HASH MD5=ad319249932c6794b551d954b8844402)
FetchContent_MakeAvailable(portaudio)
################################################################################
# libsndfile
################################################################################
FetchContent_Declare(
libsndfile
GIT_REPOSITORY https://github.com/libsndfile/libsndfile
GIT_TAG 1.1.0)
FetchContent_MakeAvailable(libsndfile)

View File

@ -33,6 +33,10 @@ Load the demo 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/).
# Community
* https://www.reddit.com/r/samplebrain/
# Download # Download

View File

@ -19,7 +19,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QLineEdit> #include <QLineEdit>
#include <QMessageBox> #include <QMessageBox>
#include "ui_samplebrain.h" #include "gui/ui_samplebrain.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
#include <iostream> #include <iostream>

View File

@ -21,7 +21,7 @@
#include <QDialog> #include <QDialog>
#include <QLineEdit> #include <QLineEdit>
#include <QSettings> #include <QSettings>
#include "ui_settings.h" #include "gui/ui_settings.h"
#include <iostream> #include <iostream>
#include <lo/lo.h> #include <lo/lo.h>

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1188</width> <width>1188</width>
<height>898</height> <height>939</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -1473,7 +1473,7 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../app/samplebrain.qrc"> <iconset resource="../samplebrain.qrc">
<normaloff>:/images/images/play.png</normaloff>:/images/images/play.png</iconset> <normaloff>:/images/images/play.png</normaloff>:/images/images/play.png</iconset>
</property> </property>
<property name="iconSize"> <property name="iconSize">
@ -1500,7 +1500,7 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../app/samplebrain.qrc"> <iconset resource="../samplebrain.qrc">
<normaloff>:/images/images/pause.png</normaloff>:/images/images/pause.png</iconset> <normaloff>:/images/images/pause.png</normaloff>:/images/images/pause.png</iconset>
</property> </property>
<property name="iconSize"> <property name="iconSize">
@ -1520,7 +1520,7 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../app/samplebrain.qrc"> <iconset resource="../samplebrain.qrc">
<normaloff>:/images/images/record.png</normaloff>:/images/images/record.png</iconset> <normaloff>:/images/images/record.png</normaloff>:/images/images/record.png</iconset>
</property> </property>
<property name="iconSize"> <property name="iconSize">
@ -1540,7 +1540,7 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../app/samplebrain.qrc"> <iconset resource="../samplebrain.qrc">
<normaloff>:/images/images/stop.png</normaloff>:/images/images/stop.png</iconset> <normaloff>:/images/images/stop.png</normaloff>:/images/images/stop.png</iconset>
</property> </property>
<property name="iconSize"> <property name="iconSize">
@ -1606,7 +1606,7 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset resource="../app/samplebrain.qrc"> <iconset resource="../samplebrain.qrc">
<normaloff>:/images/images/settings.png</normaloff>:/images/images/settings.png</iconset> <normaloff>:/images/images/settings.png</normaloff>:/images/images/settings.png</iconset>
</property> </property>
<property name="iconSize"> <property name="iconSize">
@ -1639,7 +1639,7 @@
<string/> <string/>
</property> </property>
<property name="pixmap"> <property name="pixmap">
<pixmap resource="../app/samplebrain.qrc">:/images/images/at.png</pixmap> <pixmap resource="../samplebrain.qrc">:/images/images/at.png</pixmap>
</property> </property>
</widget> </widget>
</item> </item>
@ -1650,7 +1650,8 @@
<widget class="QStatusBar" name="statusbar"/> <widget class="QStatusBar" name="statusbar"/>
</widget> </widget>
<resources> <resources>
<include location="../app/samplebrain.qrc"/> <include location="../samplebrain.qrc"/>
<include location="../samplebrain.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>

View File

@ -33,7 +33,7 @@ int main( int argc , char *argv[] ){
QApplication app(argc, argv); QApplication app(argc, argv);
cerr<<"Qt version: "<<qVersion()<<endl;
QSettings settings("thentrythis", "samplebrain"); QSettings settings("thentrythis", "samplebrain");
// slight over-use of OSC servers here, but the are packaged nicely for // slight over-use of OSC servers here, but the are packaged nicely for

View File

@ -16,6 +16,7 @@
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <atomic>
#include <sndfile.h> #include <sndfile.h>
#include <float.h> #include <float.h>
#include <spiralcore/audio.h> #include <spiralcore/audio.h>
@ -245,10 +246,12 @@ void brain::build_synapses_thresh(search_params &params, double thresh) {
m_average_error = calc_average_diff(params)*thresh; m_average_error = calc_average_diff(params)*thresh;
double err = m_average_error*thresh; double err = m_average_error*thresh;
u32 brain_size = m_blocks.size(); u32 brain_size = m_blocks.size();
u32 outer_index = 0; std::atomic<u32> progress{0};
for (auto &i : m_blocks) { #pragma omp parallel for
for (u32 outer_index = 0; outer_index < brain_size; ++outer_index) {
auto &i = m_blocks[outer_index];
u32 index = 0; u32 index = 0;
status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); status::update("building synapses %d%%",(int)(progress/(float)brain_size*100));
for (auto &j : m_blocks) { for (auto &j : m_blocks) {
if (index!=outer_index) { if (index!=outer_index) {
// collect connections that are under threshold in closeness // collect connections that are under threshold in closeness
@ -259,7 +262,7 @@ void brain::build_synapses_thresh(search_params &params, double thresh) {
} }
++index; ++index;
} }
++outer_index; ++progress;
} }
} }
*/ */
@ -267,23 +270,25 @@ void brain::build_synapses_thresh(search_params &params, double thresh) {
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;
u32 brain_size = m_blocks.size(); u32 brain_size = m_blocks.size();
u32 outer_index = 0;
u32 num_synapses = NUM_FIXED_SYNAPSES; u32 num_synapses = NUM_FIXED_SYNAPSES;
if (num_synapses>=m_blocks.size()) num_synapses=m_blocks.size()-1; if (num_synapses>=m_blocks.size()) num_synapses=m_blocks.size()-1;
// need to stop the progress updates flooding osc // need to stop the progress updates flooding osc
u32 update_period = 100; u32 update_period = 100;
u32 update_tick = 0; std::atomic<u32> update_tick{0};
std::atomic<u32> progress{0};
for (auto &i:m_blocks) { #pragma omp parallel for
for (u32 outer_index = 0; outer_index < brain_size; ++outer_index) {
auto &i = m_blocks[outer_index];
if (update_tick>update_period) { if (update_tick>update_period) {
status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); status::update("building synapses %d%%",(int)(progress/(float)brain_size*100));
update_tick=0; update_tick=0;
} }
update_tick++; update_tick++;
u32 index = 0; u32 index = 0;
vector<pair<u32,double>> collect; vector<pair<u32,double>> collect;
collect.reserve(brain_size);
// collect comparisons to all other blocks // collect comparisons to all other blocks
for (auto &j:m_blocks) { for (auto &j:m_blocks) {
@ -308,7 +313,7 @@ void brain::build_synapses_fixed(search_params &params) {
i.get_synapse().push_back(collect[n].first); i.get_synapse().push_back(collect[n].first);
} }
++outer_index; ++progress;
} }
status::update("Done: %d synapses grown for %d blocks",num_synapses*brain_size,brain_size); status::update("Done: %d synapses grown for %d blocks",num_synapses*brain_size,brain_size);
} }

View File

@ -60,7 +60,7 @@ void OSC_server::error_handler(int num, const char *msg, const char *path) {
} }
int OSC_server::default_handler(const char *path, const char *types, lo_arg **argv, int OSC_server::default_handler(const char *path, const char *types, lo_arg **argv,
int argc, lo_message data, void *user_data) { int argc, void *data, void *user_data) {
OSC_server *server = (OSC_server*)user_data; OSC_server *server = (OSC_server*)user_data;
if (!server) return -1; if (!server) return -1;

View File

@ -32,7 +32,7 @@ public:
bool ok() { return m_server!=NULL; } bool ok() { return m_server!=NULL; }
private: private:
static int default_handler(const char *path, const char *types, lo_arg **argv, int argc, lo_message data, void *user_data); static int default_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data);
static void error_handler(int num, const char *m, const char *path); static void error_handler(int num, const char *m, const char *path);
lo_server_thread m_server; lo_server_thread m_server;

View File

@ -1,8 +1,8 @@
# Building from source # Building from source
## Linux (Ubuntu) ## Linux (Ubuntu)
Install libraries for the sample engine (use brew on mac, MinGW on win): Install cmake:
$ sudo apt install libsndfile1-dev portaudio19-dev liblo-dev libfftw3-dev $ sudo apt install cmake
Install dependencies for the interface: Install dependencies for the interface:
@ -16,15 +16,14 @@ Build & run it:
$ mkdir build $ mkdir build
$ cd build $ cd build
$ qmake .. $ cmake ..
$ make $ cmake --build .
$ sudo make install $ ./samplebrain
$ samplebrain
## Mac ## Mac
Install libraries for sample engine: Install cmake:
$ brew install fftw portaudio liblo libsndfile $ brew install cmake
Install dependencies for the interface: Install dependencies for the interface:
@ -35,10 +34,10 @@ Build & run it:
$ mkdir build $ mkdir build
$ cd build $ cd build
$ qmake .. $ cmake ..
$ make $ cmake --build .
`samplebrain.app` should then be in the app folder for you to run. `samplebrain.app` should then be in the build folder for you to run.
# Mac build additions # Mac build additions

View File

@ -1,71 +0,0 @@
######################################################################
# Automatically generated by qmake (2.01a) Sun Jul 5 17:49:45 2015
######################################################################
TEMPLATE = app
TARGET = samplebrain
DEPENDPATH += . 2
INCLUDEPATH += . 2
QT += core gui widgets
# Input
HEADERS += app/MainWindow.h \
app/SettingsDialog.h
FORMS += gui/samplebrain.ui \
gui/settings.ui
SOURCES += app/MainWindow.cpp \
app/SettingsDialog.cpp \
app/sound_items.cpp \
app/audio_thread.cpp \
app/process_thread.cpp \
app/feedback.cpp \
app/qtmain.cpp \
brain/src/block.cpp \
brain/src/brain.cpp \
brain/src/fft.cpp \
brain/src/mfcc.cpp \
brain/src/renderer.cpp \
brain/src/search_params.cpp \
brain/src/status.cpp \
brain/src/window.cpp \
brain/src/block_stream.cpp \
brain/src/aquila/filter/MelFilterBank.cpp \
brain/src/aquila/filter/MelFilter.cpp \
brain/src/aquila/transform/Dct.cpp \
brain/src/spiralcore/sample.cpp \
brain/src/spiralcore/ring_buffer.cpp \
brain/src/spiralcore/command_ring_buffer.cpp \
brain/src/spiralcore/portaudio_client.cpp \
brain/src/spiralcore/audio.cpp \
brain/src/spiralcore/OSC_server.cpp \
brain/src/spiralcore/allocator.cpp \
brain/src/spiralcore/stream.cpp
INCLUDEPATH += brain/src
INCLUDEPATH += /usr/local/include
INCLUDEPATH += /opt/homebrew/include
LIBS += -L.. -L/usr/local/lib -L/opt/homebrew/lib -lportaudio -lfftw3 -lsndfile -llo -ldl -lpthread -lm
QMAKE_CXXFLAGS += -O3 -Wall -Wno-unused -std=c++11
# assets
RESOURCES = app/samplebrain.qrc
ICON = desktop/samplebrain.icns
PREFIX = $$(PREFIX)
isEmpty(PREFIX) {
PREFIX = /usr
}
unix:desktopfile.path = $$PREFIX/share/applications/
unix:desktopfile.files = desktop/samplebrain.desktop
unix:iconfile.path = $$PREFIX/share/icons/hicolor/scalable/apps
unix:iconfile.files = desktop/samplebrain.svg
unix:metainfofile.path = $$PREFIX/share/metainfo
unix:metainfofile.files = desktop/org.thentrythis.Samplebrain.metainfo.xml
target.path = $$PREFIX/bin
INSTALLS += target desktopfile iconfile metainfofile