mix options, render glitch fix, fft bins, interface rework

This commit is contained in:
Dave Griffiths 2015-07-22 15:32:36 +01:00
parent 3f2b86c171
commit fabd9cbe4f
13 changed files with 427 additions and 72 deletions

View File

@ -14,7 +14,7 @@
<string>samplebrain 0.0.4</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_7">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="font">
@ -31,7 +31,7 @@
<attribute name="title">
<string>search</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
@ -45,7 +45,7 @@
</font>
</property>
<property name="text">
<string>tweakage</string>
<string>search</string>
</property>
</widget>
</item>
@ -54,13 +54,13 @@
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>14</pointsize>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>fft &lt;-&gt; mfcc ratio</string>
<string>fft &lt;-&gt; mfcc</string>
</property>
</widget>
</item>
@ -108,13 +108,13 @@
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>14</pointsize>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>freq &amp; dynamics &lt;-&gt; freq ratio</string>
<string>freq &amp; dynamics &lt;-&gt; freq only</string>
</property>
</widget>
</item>
@ -129,7 +129,7 @@
</sizepolicy>
</property>
<property name="value">
<number>50</number>
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -151,7 +151,7 @@
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.500000000000000</double>
<double>0.000000000000000</double>
</property>
</widget>
</item>
@ -162,7 +162,7 @@
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>14</pointsize>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
@ -223,7 +223,7 @@
</size>
</property>
<property name="text">
<string>invert</string>
<string>search for least similar</string>
</property>
<property name="iconSize">
<size>
@ -233,6 +233,132 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_23">
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>20</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>mix</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_21">
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>dynamic &lt;-&gt; normalised mix</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QSlider" name="sliderNMix">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxNMix">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_22">
<property name="font">
<font>
<family>Comic Sans MS</family>
<pointsize>9</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>brain &lt;-&gt; target mix</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QSlider" name="sliderTargetMix">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="value">
<number>0</number>
</property>
<property name="sliderPosition">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="doubleSpinBoxTargetMix">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
@ -332,7 +458,7 @@
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.750000000000000</double>
<double>0.000000000000000</double>
</property>
</widget>
</item>
@ -514,7 +640,7 @@
<double>0.010000000000000</double>
</property>
<property name="value">
<double>0.750000000000000</double>
<double>0.000000000000000</double>
</property>
</widget>
</item>
@ -866,6 +992,7 @@
</widget>
<resources>
<include location="../qt/samplebrain.qrc"/>
<include location="../../../../.designer/qt/samplebrain.qrc"/>
</resources>
<connections>
<connection>
@ -1476,6 +1603,70 @@
</hint>
</hints>
</connection>
<connection>
<sender>sliderNMix</sender>
<signal>valueChanged(int)</signal>
<receiver>MainWindow</receiver>
<slot>n_mix_slot(int)</slot>
<hints>
<hint type="sourcelabel">
<x>159</x>
<y>386</y>
</hint>
<hint type="destinationlabel">
<x>361</x>
<y>306</y>
</hint>
</hints>
</connection>
<connection>
<sender>sliderTargetMix</sender>
<signal>valueChanged(int)</signal>
<receiver>MainWindow</receiver>
<slot>target_mix_slot(int)</slot>
<hints>
<hint type="sourcelabel">
<x>159</x>
<y>446</y>
</hint>
<hint type="destinationlabel">
<x>361</x>
<y>306</y>
</hint>
</hints>
</connection>
<connection>
<sender>doubleSpinBoxNMix</sender>
<signal>valueChanged(double)</signal>
<receiver>MainWindow</receiver>
<slot>n_mix_slot(double)</slot>
<hints>
<hint type="sourcelabel">
<x>330</x>
<y>386</y>
</hint>
<hint type="destinationlabel">
<x>361</x>
<y>306</y>
</hint>
</hints>
</connection>
<connection>
<sender>doubleSpinBoxTargetMix</sender>
<signal>valueChanged(double)</signal>
<receiver>MainWindow</receiver>
<slot>target_mix_slot(double)</slot>
<hints>
<hint type="sourcelabel">
<x>330</x>
<y>446</y>
</hint>
<hint type="destinationlabel">
<x>361</x>
<y>306</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>play_slot()</slot>
@ -1522,5 +1713,9 @@
<slot>n_ratio_slot(int)</slot>
<slot>n_ratio_slot(double)</slot>
<slot>invert_slot(bool)</slot>
<slot>n_mix_slot(int)</slot>
<slot>n_mix_slot(double)</slot>
<slot>target_mix_slot(int)</slot>
<slot>target_mix_slot(double)</slot>
</slots>
</ui>

View File

@ -48,6 +48,10 @@ private slots:
void fft1_end_slot(int s) { lo_send(m_audio_address,"/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) { lo_send(m_audio_address,"/n_mix","f",s/100.0f); }
void n_mix_slot(double s) { lo_send(m_audio_address,"/n_mix","f",s); }
void target_mix_slot(int s) { lo_send(m_audio_address,"/target_mix","f",s/100.0f); }
void target_mix_slot(double s) { lo_send(m_audio_address,"/target_mix","f",s); }
void volume_slot(int s) { lo_send(m_audio_address,"/volume","f",s/100.0f); }
void invert_slot(bool s) { if (s) {
lo_send(m_audio_address,"/invert","i",1);

View File

@ -91,6 +91,12 @@ void audio_thread::process(sample &s, sample &s2) {
if (name=="/invert") {
m_renderer->set_invert(cmd.get_int(0));
}
if (name=="/n_mix") {
m_renderer->set_n_mix(cmd.get_float(0));
}
if (name=="/target_mix") {
m_renderer->set_target_mix(cmd.get_float(0));
}
if (name=="/record") {
m_renderer->set_playing(true);
m_audio_device->start_recording(cmd.get_string(0));

View File

@ -1,14 +1,14 @@
/********************************************************************************
** Form generated from reading UI file 'samplebrainm32443.ui'
** Form generated from reading UI file 'samplebrainC26316.ui'
**
** Created: Tue Jul 21 22:01:28 2015
** Created: Wed Jul 22 15:20:00 2015
** by: Qt User Interface Compiler version 4.8.1
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef SAMPLEBRAINM32443_H
#define SAMPLEBRAINM32443_H
#ifndef SAMPLEBRAINC26316_H
#define SAMPLEBRAINC26316_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
@ -40,10 +40,10 @@ class Ui_MainWindow
{
public:
QWidget *centralwidget;
QVBoxLayout *verticalLayout_7;
QVBoxLayout *verticalLayout_4;
QTabWidget *tabWidget;
QWidget *controlTab;
QHBoxLayout *horizontalLayout_8;
QHBoxLayout *horizontalLayout_10;
QVBoxLayout *verticalLayout_3;
QLabel *label_19;
QLabel *label_6;
@ -61,6 +61,15 @@ public:
QLabel *label_10;
QSpinBox *spinBoxFFT1End;
QCheckBox *checkBoxInvert;
QLabel *label_23;
QLabel *label_21;
QHBoxLayout *horizontalLayout_8;
QSlider *sliderNMix;
QDoubleSpinBox *doubleSpinBoxNMix;
QLabel *label_22;
QHBoxLayout *horizontalLayout_9;
QSlider *sliderTargetMix;
QDoubleSpinBox *doubleSpinBoxTargetMix;
QSpacerItem *verticalSpacer_3;
QVBoxLayout *verticalLayout_6;
QLabel *label_16;
@ -135,8 +144,8 @@ public:
MainWindow->resize(724, 613);
centralwidget = new QWidget(MainWindow);
centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
verticalLayout_7 = new QVBoxLayout(centralwidget);
verticalLayout_7->setObjectName(QString::fromUtf8("verticalLayout_7"));
verticalLayout_4 = new QVBoxLayout(centralwidget);
verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4"));
tabWidget = new QTabWidget(centralwidget);
tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
QFont font;
@ -146,8 +155,8 @@ public:
tabWidget->setFont(font);
controlTab = new QWidget();
controlTab->setObjectName(QString::fromUtf8("controlTab"));
horizontalLayout_8 = new QHBoxLayout(controlTab);
horizontalLayout_8->setObjectName(QString::fromUtf8("horizontalLayout_8"));
horizontalLayout_10 = new QHBoxLayout(controlTab);
horizontalLayout_10->setObjectName(QString::fromUtf8("horizontalLayout_10"));
verticalLayout_3 = new QVBoxLayout();
verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3"));
label_19 = new QLabel(controlTab);
@ -165,7 +174,7 @@ public:
label_6->setObjectName(QString::fromUtf8("label_6"));
QFont font2;
font2.setFamily(QString::fromUtf8("Comic Sans MS"));
font2.setPointSize(14);
font2.setPointSize(9);
font2.setBold(true);
font2.setWeight(75);
label_6->setFont(font2);
@ -214,7 +223,7 @@ public:
sliderNRatio->setObjectName(QString::fromUtf8("sliderNRatio"));
sizePolicy.setHeightForWidth(sliderNRatio->sizePolicy().hasHeightForWidth());
sliderNRatio->setSizePolicy(sizePolicy);
sliderNRatio->setValue(50);
sliderNRatio->setValue(0);
sliderNRatio->setOrientation(Qt::Horizontal);
horizontalLayout->addWidget(sliderNRatio);
@ -225,7 +234,7 @@ public:
doubleSpinBoxNRatio->setSizePolicy(sizePolicy1);
doubleSpinBoxNRatio->setMaximum(1);
doubleSpinBoxNRatio->setSingleStep(0.01);
doubleSpinBoxNRatio->setValue(0.5);
doubleSpinBoxNRatio->setValue(0);
horizontalLayout->addWidget(doubleSpinBoxNRatio);
@ -273,12 +282,79 @@ public:
verticalLayout_3->addWidget(checkBoxInvert);
label_23 = new QLabel(controlTab);
label_23->setObjectName(QString::fromUtf8("label_23"));
label_23->setFont(font1);
verticalLayout_3->addWidget(label_23);
label_21 = new QLabel(controlTab);
label_21->setObjectName(QString::fromUtf8("label_21"));
label_21->setFont(font2);
verticalLayout_3->addWidget(label_21);
horizontalLayout_8 = new QHBoxLayout();
horizontalLayout_8->setObjectName(QString::fromUtf8("horizontalLayout_8"));
sliderNMix = new QSlider(controlTab);
sliderNMix->setObjectName(QString::fromUtf8("sliderNMix"));
sizePolicy.setHeightForWidth(sliderNMix->sizePolicy().hasHeightForWidth());
sliderNMix->setSizePolicy(sizePolicy);
sliderNMix->setValue(0);
sliderNMix->setOrientation(Qt::Horizontal);
horizontalLayout_8->addWidget(sliderNMix);
doubleSpinBoxNMix = new QDoubleSpinBox(controlTab);
doubleSpinBoxNMix->setObjectName(QString::fromUtf8("doubleSpinBoxNMix"));
sizePolicy1.setHeightForWidth(doubleSpinBoxNMix->sizePolicy().hasHeightForWidth());
doubleSpinBoxNMix->setSizePolicy(sizePolicy1);
doubleSpinBoxNMix->setMaximum(1);
doubleSpinBoxNMix->setSingleStep(0.01);
doubleSpinBoxNMix->setValue(0);
horizontalLayout_8->addWidget(doubleSpinBoxNMix);
verticalLayout_3->addLayout(horizontalLayout_8);
label_22 = new QLabel(controlTab);
label_22->setObjectName(QString::fromUtf8("label_22"));
label_22->setFont(font2);
verticalLayout_3->addWidget(label_22);
horizontalLayout_9 = new QHBoxLayout();
horizontalLayout_9->setObjectName(QString::fromUtf8("horizontalLayout_9"));
sliderTargetMix = new QSlider(controlTab);
sliderTargetMix->setObjectName(QString::fromUtf8("sliderTargetMix"));
sizePolicy.setHeightForWidth(sliderTargetMix->sizePolicy().hasHeightForWidth());
sliderTargetMix->setSizePolicy(sizePolicy);
sliderTargetMix->setValue(0);
sliderTargetMix->setSliderPosition(0);
sliderTargetMix->setOrientation(Qt::Horizontal);
horizontalLayout_9->addWidget(sliderTargetMix);
doubleSpinBoxTargetMix = new QDoubleSpinBox(controlTab);
doubleSpinBoxTargetMix->setObjectName(QString::fromUtf8("doubleSpinBoxTargetMix"));
sizePolicy1.setHeightForWidth(doubleSpinBoxTargetMix->sizePolicy().hasHeightForWidth());
doubleSpinBoxTargetMix->setSizePolicy(sizePolicy1);
doubleSpinBoxTargetMix->setMaximum(1);
doubleSpinBoxTargetMix->setSingleStep(0.01);
doubleSpinBoxTargetMix->setValue(0);
horizontalLayout_9->addWidget(doubleSpinBoxTargetMix);
verticalLayout_3->addLayout(horizontalLayout_9);
verticalSpacer_3 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalLayout_3->addItem(verticalSpacer_3);
horizontalLayout_8->addLayout(verticalLayout_3);
horizontalLayout_10->addLayout(verticalLayout_3);
verticalLayout_6 = new QVBoxLayout();
verticalLayout_6->setObjectName(QString::fromUtf8("verticalLayout_6"));
@ -324,7 +400,7 @@ public:
doubleSpinBoxBlockOverlapTarget->setObjectName(QString::fromUtf8("doubleSpinBoxBlockOverlapTarget"));
doubleSpinBoxBlockOverlapTarget->setMaximum(1);
doubleSpinBoxBlockOverlapTarget->setSingleStep(0.01);
doubleSpinBoxBlockOverlapTarget->setValue(0.75);
doubleSpinBoxBlockOverlapTarget->setValue(0);
horizontalLayout_14->addWidget(doubleSpinBoxBlockOverlapTarget);
@ -393,7 +469,7 @@ public:
verticalLayout_6->addItem(verticalSpacer);
horizontalLayout_8->addLayout(verticalLayout_6);
horizontalLayout_10->addLayout(verticalLayout_6);
tabWidget->addTab(controlTab, QString());
sampleTab = new QWidget();
@ -438,7 +514,7 @@ public:
doubleSpinBoxBlockOverlap->setObjectName(QString::fromUtf8("doubleSpinBoxBlockOverlap"));
doubleSpinBoxBlockOverlap->setMaximum(1);
doubleSpinBoxBlockOverlap->setSingleStep(0.01);
doubleSpinBoxBlockOverlap->setValue(0.75);
doubleSpinBoxBlockOverlap->setValue(0);
horizontalLayout_6->addWidget(doubleSpinBoxBlockOverlap);
@ -577,7 +653,7 @@ public:
tabWidget->addTab(logTab, QString());
verticalLayout_7->addWidget(tabWidget);
verticalLayout_4->addWidget(tabWidget);
horizontalLayout_12 = new QHBoxLayout();
horizontalLayout_12->setObjectName(QString::fromUtf8("horizontalLayout_12"));
@ -640,7 +716,7 @@ public:
horizontalLayout_12->addWidget(label_13);
verticalLayout_7->addLayout(horizontalLayout_12);
verticalLayout_4->addLayout(horizontalLayout_12);
MainWindow->setCentralWidget(centralwidget);
statusbar = new QStatusBar(MainWindow);
@ -686,6 +762,10 @@ public:
QObject::connect(sliderNRatio, SIGNAL(valueChanged(int)), MainWindow, SLOT(n_ratio_slot(int)));
QObject::connect(doubleSpinBoxNRatio, SIGNAL(valueChanged(double)), MainWindow, SLOT(n_ratio_slot(double)));
QObject::connect(checkBoxInvert, SIGNAL(toggled(bool)), MainWindow, SLOT(invert_slot(bool)));
QObject::connect(sliderNMix, SIGNAL(valueChanged(int)), MainWindow, SLOT(n_mix_slot(int)));
QObject::connect(sliderTargetMix, SIGNAL(valueChanged(int)), MainWindow, SLOT(target_mix_slot(int)));
QObject::connect(doubleSpinBoxNMix, SIGNAL(valueChanged(double)), MainWindow, SLOT(n_mix_slot(double)));
QObject::connect(doubleSpinBoxTargetMix, SIGNAL(valueChanged(double)), MainWindow, SLOT(target_mix_slot(double)));
tabWidget->setCurrentIndex(0);
@ -696,13 +776,16 @@ public:
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "samplebrain 0.0.4", 0, QApplication::UnicodeUTF8));
label_19->setText(QApplication::translate("MainWindow", "tweakage", 0, QApplication::UnicodeUTF8));
label_6->setText(QApplication::translate("MainWindow", "fft <-> mfcc ratio", 0, QApplication::UnicodeUTF8));
label_20->setText(QApplication::translate("MainWindow", "freq & dynamics <-> freq ratio", 0, QApplication::UnicodeUTF8));
label_19->setText(QApplication::translate("MainWindow", "search", 0, QApplication::UnicodeUTF8));
label_6->setText(QApplication::translate("MainWindow", "fft <-> mfcc", 0, QApplication::UnicodeUTF8));
label_20->setText(QApplication::translate("MainWindow", "freq & dynamics <-> freq only", 0, QApplication::UnicodeUTF8));
label_7->setText(QApplication::translate("MainWindow", "fft subsection", 0, QApplication::UnicodeUTF8));
label_9->setText(QApplication::translate("MainWindow", "Start", 0, QApplication::UnicodeUTF8));
label_10->setText(QApplication::translate("MainWindow", "End", 0, QApplication::UnicodeUTF8));
checkBoxInvert->setText(QApplication::translate("MainWindow", "invert", 0, QApplication::UnicodeUTF8));
checkBoxInvert->setText(QApplication::translate("MainWindow", "search for least similar", 0, QApplication::UnicodeUTF8));
label_23->setText(QApplication::translate("MainWindow", "mix", 0, QApplication::UnicodeUTF8));
label_21->setText(QApplication::translate("MainWindow", "dynamic <-> normalised mix", 0, QApplication::UnicodeUTF8));
label_22->setText(QApplication::translate("MainWindow", "brain <-> target mix", 0, QApplication::UnicodeUTF8));
label_16->setText(QApplication::translate("MainWindow", "target sound", 0, QApplication::UnicodeUTF8));
pushButtonLoadTarget->setText(QApplication::translate("MainWindow", "load target", 0, QApplication::UnicodeUTF8));
label_17->setText(QApplication::translate("MainWindow", "block size", 0, QApplication::UnicodeUTF8));
@ -754,4 +837,4 @@ namespace Ui {
QT_END_NAMESPACE
#endif // SAMPLEBRAINM32443_H
#endif // SAMPLEBRAINC26316_H

View File

@ -88,7 +88,7 @@ void block::init_fft(u32 block_size)
{
if (m_fftw == NULL || m_fftw->m_length!=block_size) {
if (m_fftw == NULL) delete m_fftw;
m_fftw = new FFT(block_size);
m_fftw = new FFT(block_size,100);
if (m_mfcc_proc == NULL) delete m_mfcc_proc;
m_mfcc_proc = new Aquila::Mfcc(block_size);
}
@ -96,16 +96,25 @@ void block::init_fft(u32 block_size)
void block::process(const sample &pcm, sample &fft, sample &mfcc) {
m_fftw->impulse2freq(pcm.get_buffer());
m_fftw->calculate_bins();
// calculate fft
std::vector<std::complex<double> > mfspec;
for (u32 i=0; i<m_block_size; ++i) {
fft[i]=m_fftw->m_spectrum[i][0];
mfspec.push_back(std::complex<double>(m_fftw->m_spectrum[i][0],
m_fftw->m_spectrum[i][1]));
}
if (m_block_size>100) fft.crop_to(100);
u32 fft_size = m_block_size;
if (fft_size>100) {
fft.crop_to(100);
fft_size=100;
}
for (u32 i=0; i<fft_size; ++i) {
fft[i]=m_fftw->m_bin[i];
}
// calculate mfcc
std::vector<double> m = m_mfcc_proc->calculate(mfspec,MFCC_FILTERS);

View File

@ -39,6 +39,7 @@ public:
static bool unit_test();
const sample &get_pcm() const { return m_pcm; }
const sample &get_n_pcm() const { return m_n_pcm; }
private:

View File

@ -74,10 +74,6 @@ void brain::chop_and_add(const sample &s, bool ditchpcm) {
}
}
const sample &brain::get_block_pcm(u32 index) const {
return m_blocks[index].get_pcm();
}
const block &brain::get_block(u32 index) const {
return m_blocks[index];
}
@ -116,7 +112,7 @@ u32 brain::rev_search(const block &target, const search_params &params) const {
// 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){
/*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;
@ -139,7 +135,7 @@ void brain::resynth(const string &filename, const brain &other, const search_par
}
audio_device::save_sample(filename,out);
}
*/
bool brain::unit_test() {
brain b;

View File

@ -51,9 +51,10 @@ public:
void clear_sounds() { m_samples.clear(); }
// take another brain and rebuild this brain from bits of that one
// (presumably this one is made from a single sample)
void resynth(const std::string &filename, const brain &other, const search_params &params);
//void resynth(const std::string &filename, const brain &other, const search_params &params);
const sample &get_block_pcm(u32 index) const;
const sample &get_block_n_pcm(u32 index) const;
const block &get_block(u32 index) const;
u32 get_num_blocks() const { return m_blocks.size(); }
u32 get_block_size() const { return m_block_size; }

View File

@ -15,16 +15,20 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <fft.h>
#include <jellyfish/core/types.h>
#include <iostream>
using namespace spiralcore;
using namespace std;
static const int MAX_FFT_LENGTH = 4096;
FFT::FFT(int length) :
FFT::FFT(u32 length, u32 bins) :
m_length(length),
m_num_bins(bins),
m_in(new double[length]),
m_spectrum(new fftw_complex[length])
m_spectrum(new fftw_complex[length]),
m_bin(new float[bins])
{
m_plan = fftw_plan_dft_r2c_1d(m_length, m_in, m_spectrum, FFTW_ESTIMATE);
}
@ -46,3 +50,31 @@ void FFT::impulse2freq(const float *imp)
fftw_execute(m_plan);
}
void FFT::calculate_bins() {
float useful_area = m_length/2;
for (unsigned int n=0; n<m_num_bins; n++) {
float value = 0;
float f = n/(float)m_num_bins;
float t = (n+1)/(float)m_num_bins;
//f*=f;
//t*=t;
u32 from = f*useful_area;
u32 to = t*useful_area;
//cerr<<"fft bin:"<<from<<" "<<to<<" - "<<m_length<<endl;
for (u32 i=from; i<=to; i++) {
if (i<m_length) {
value += m_spectrum[i][0];
}
}
if (value<0) value=-value;
m_bin[n]=value;
}
}

View File

@ -15,6 +15,7 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <fftw3.h>
#include <jellyfish/core/types.h>
#ifndef SPIRALCORE_FFT
#define SPIRALCORE_FFT
@ -26,14 +27,17 @@ namespace spiralcore {
class FFT
{
public:
FFT(int length);
FFT(u32 length, u32 num_bins);
~FFT();
void impulse2freq(const float *imp);
void calculate_bins();
fftw_plan m_plan;
unsigned int m_length;
u32 m_length;
u32 m_num_bins;
double *m_in;
fftw_complex *m_spectrum;
float *m_bin;
};
}

View File

@ -48,6 +48,8 @@ void run_audio(void* c, unsigned int frames) {
renderer *rr = (renderer*)c;
rr->process(frames,a->left_out.get_non_const_buffer());
a->maybe_record();
// sleep(1);
}
@ -59,24 +61,25 @@ int main(int argc, char *argv[])
brain source, target;
// source.load_sound("../sound/source/shostakovich6.wav");
source.load_sound("../sound/source/808.wav");
/* source.load_sound("../sound/source/808.wav");
source.load_sound("../sound/source/joey.wav");
source.load_sound("../sound/source/pw2.wav");
source.load_sound("../sound/source/pw3.wav");
source.load_sound("../sound/source/claps.wav");
source.load_sound("../sound/source/eagle.wav");
target.load_sound("../sound/source/apache.wav");
// source.load_sound("../sound/source/rise.wav");
*/
source.load_sound("../sound/source/totalsine.wav");
target.load_sound("../sound/source/sailingbybit.wav");
//target.load_sound("../sound/source/sb-left.wav");
// target.load_sound("../sound/source/rise.wav");
cerr<<"loaded sounds"<<endl;
cerr<<endl;
u32 len=3000;
source.init(len,len-len,window::DODGY);
target.init(len,len-len/4,window::DODGY);
source.init(len,len-len,window::HANN);
target.init(len,len-len,window::HANN);
cerr<<"ready..."<<endl;
cerr<<"we have "<<source.get_num_blocks()<<" brain blocks ("<<source.get_num_blocks()*len/44100.0<<" secs)"<<endl<<endl;
@ -88,6 +91,7 @@ int main(int argc, char *argv[])
rr.set_playing(true);
rr.get_params()->m_ratio=0.5;
a->start_recording("debug");
a->m_client.set_callback(run_audio, &rr);
//target.resynth("shosta-dream-0.5.wav",source,0.5);

View File

@ -22,10 +22,13 @@ using namespace std;
void renderer::init(brain &source, brain &target) {
m_volume=1;
m_invert=false;
m_playing=false;
m_source=source;
m_target=target;
m_render_time=0;
m_n_mix=0;
m_target_mix=0;
m_render_blocks.clear();
}
@ -34,7 +37,7 @@ static int ratio_time = 0;
void renderer::process(u32 nframes, float *buf) {
if (!m_playing) return;
// get blocks from source for the current buffer
// get new blocks from source for the current buffer
u32 tgt_shift = m_target.get_block_size()-m_target.get_overlap();
u32 tgt_start = m_render_time/(float)tgt_shift;
u32 tgt_end = (m_render_time+nframes)/(float)tgt_shift;
@ -52,7 +55,7 @@ void renderer::process(u32 nframes, float *buf) {
//cerr<<"tgt end:"<<tgt_end<<endl;
// get indices for current buffer
for (u32 tgt_index = tgt_start; tgt_index<=tgt_end; tgt_index++) {
for (u32 tgt_index = tgt_start+1; tgt_index<=tgt_end; tgt_index++) {
u32 time=tgt_index*tgt_shift;
u32 src_index;
if (!m_invert) {
@ -61,12 +64,14 @@ void renderer::process(u32 nframes, float *buf) {
src_index = m_source.rev_search(m_target.get_block(tgt_index), m_search_params);
}
// put them in the index list
m_render_blocks.push_back(render_block(src_index,time));
m_render_blocks.push_back(render_block(src_index,tgt_index,time));
}
// render all blocks in list
for (std::list<render_block>::iterator i=m_render_blocks.begin(); i!=m_render_blocks.end(); ++i) {
const sample &pcm=m_source.get_block_pcm(i->m_index);
const sample &pcm=m_source.get_block(i->m_index).get_pcm();
const sample &n_pcm=m_source.get_block(i->m_index).get_n_pcm();
const sample &target_pcm=m_target.get_block(i->m_tgt_index).get_pcm();
// get the sample offset into the buffer
s32 offset = i->m_time-m_render_time;
@ -90,8 +95,18 @@ void renderer::process(u32 nframes, float *buf) {
u32 buffer_pos = buffer_start;
u32 block_pos = block_start;
u32 block_end = pcm.get_length();
while (block_pos<block_end && buffer_pos<nframes) {
buf[buffer_pos]+=pcm[block_pos]*0.2*m_volume;
// mix with normalised version
float brain_sample = (pcm[block_pos]*(1-m_n_mix)+
n_pcm[block_pos]*m_n_mix);
// for mixing with target audio
float target_sample = target_pcm[block_pos];
buf[buffer_pos]+=(brain_sample*(1-m_target_mix) +
target_sample*m_target_mix)*0.2*m_volume;
++buffer_pos;
++block_pos;
}
@ -123,19 +138,19 @@ bool renderer::unit_test() {
rr.set_playing(true);
float *buf=new float[10];
rr.process(10,buf);
assert(rr.m_render_blocks.size()==2);
assert(rr.m_render_blocks.size()==1);
rr.process(10,buf);
assert(rr.m_render_blocks.size()==3);
assert(rr.m_render_blocks.size()==2);
delete[] buf;
buf=new float[20];
rr.process(20,buf);
assert(rr.m_render_blocks.size()==4);
assert(rr.m_render_blocks.size()==3);
rr.process(5,buf);
assert(rr.m_render_blocks.size()==2);
assert(rr.m_render_blocks.size()==1);
target.init(10,5,window::RECTANGLE);
rr.process(10,buf);
assert(rr.m_render_blocks.size()==5);
assert(rr.m_render_blocks.size()==3);
delete[] buf;
}

View File

@ -37,6 +37,8 @@ renderer(brain &source, brain &target) :
void set_playing(bool s) { m_playing=s; }
void set_volume(float s) { m_volume=s; }
void set_invert(bool s) { m_invert=s; }
void set_n_mix(float s) { m_n_mix=s; }
void set_target_mix(float s) { m_target_mix=s; }
search_params *get_params() { return &m_search_params; }
static bool unit_test();
@ -46,9 +48,10 @@ private:
// realtime stuff
class render_block {
public:
render_block(u32 index, u32 time) :
m_index(index), m_time(time), m_finished(false) {}
render_block(u32 index, u32 tgt_index, u32 time) :
m_index(index), m_tgt_index(tgt_index), m_time(time), m_finished(false) {}
u32 m_index;
u32 m_tgt_index; // original target block
u32 m_time; // in samples
bool m_finished;
};
@ -62,6 +65,8 @@ private:
bool m_invert;
std::list<render_block> m_render_blocks;
u32 m_render_time;
float m_n_mix;
float m_target_mix;
};
}