some working tests, some segfaults

This commit is contained in:
Dave Griffiths 2015-07-08 10:24:02 +01:00
parent 20ff4e5f52
commit 9ed6fd3e3d
10 changed files with 287 additions and 45 deletions

39
samplebrain/configure vendored
View File

@ -2990,6 +2990,45 @@ _ACEOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsndfile" >&5
$as_echo_n "checking for main in -lsndfile... " >&6; }
if ${ac_cv_lib_sndfile_main+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsndfile $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
return main ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_sndfile_main=yes
else
ac_cv_lib_sndfile_main=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sndfile_main" >&5
$as_echo "$ac_cv_lib_sndfile_main" >&6; }
if test "x$ac_cv_lib_sndfile_main" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBSNDFILE 1
_ACEOF
LIBS="-lsndfile $LIBS"
fi
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'

View File

@ -5,6 +5,7 @@ AC_CHECK_LIB(m, cos)
AC_CHECK_LIB(fftw3, main)
AC_CHECK_LIB(portaudio, main)
AC_CHECK_LIB(jellyfish, main)
AC_CHECK_LIB(sndfile, main)
AC_PROG_CXX
AC_LANG(C++)

View File

@ -0,0 +1,103 @@
#include <iostream>
#include <sndfile.h>
#include "brain.h"
using namespace std;
using namespace spiralcore;
brain::brain()
{
}
// load, chop up and add to brain
// todo: add tags
sample brain::load_sound(std::string filename) {
SF_INFO sfinfo;
sfinfo.format=0;
SNDFILE* f=sf_open(filename.c_str(), SFM_READ, &sfinfo);
sample s(sfinfo.frames);
sf_read_float(f, s.get_non_const_buffer(), s.get_length());
sf_close(f);
m_samples.push_back(s);
return s;
}
// rewrites whole brain
void brain::init(u32 block_size, u32 overlap) {
m_blocks.clear();
for (vector<sample>::iterator i=m_samples.begin(); i!=m_samples.end(); ++i) {
chop_and_add(*i, block_size, overlap);
}
}
void brain::chop_and_add(const sample &s, u32 block_size, u32 overlap) {
u32 pos=0;
while (pos+block_size-1<s.get_length()) {
sample region;
s.get_region(region,pos,pos+block_size-1);
m_blocks.push_back(brain_block("",region,44100));
pos += block_size-overlap;
}
}
// returns index to block
u32 brain::search(const brain_block &target, float ratio) {
double closest = 999999999;
u32 closest_index = 0;
u32 index = 0;
for (vector<brain_block>::iterator i=m_blocks.begin(); i!=m_blocks.end(); ++i) {
double diff = target.compare(*i,ratio);
if (diff<closest) {
closest=diff;
closest_index = index;
}
++index;
}
return closest_index;
}
// take another brain and rebuild this brain from bits of that one
// (presumably this one is made from a single sample)
sample brain::resynth(const brain &other, float ratio){
}
bool brain::unit_test() {
brain b;
assert(b.m_samples.size()==0);
assert(b.m_blocks.size()==0);
sample s=b.load_sound("test_data/100f32.wav");
assert(b.m_samples.size()==1);
assert(s.get_length()==100);
s=b.load_sound("test_data/100i16.wav");
assert(b.m_samples.size()==2);
assert(s.get_length()==100);
b.init(10, 0);
assert(b.m_samples.size()==2);
assert(b.m_blocks.size()==20);
b.init(10, 5);
assert(b.m_samples.size()==2);
assert(b.m_blocks.size()==38);
b.init(20, 5);
assert(b.m_samples.size()==2);
assert(b.m_blocks.size()==12);
// replicate brain
brain b2;
b2.load_sound("test_data/100f32.wav");
b2.load_sound("test_data/100f32.wav");
assert(b.m_samples.size()==2);
b.init(10, 0);
assert(b.m_blocks.size()==20);
assert(b.search(b2.m_blocks[0],1)==0);
assert(b.search(b2.m_blocks[19],1)==19);
return true;
}

View File

@ -1,6 +1,13 @@
#include <vector>
#include "sample.h"
#include "fft.h"
#include <string>
#include "jellyfish/core/types.h"
#include "jellyfish/fluxa/sample.h"
#include "brain_block.h"
#ifndef BRAIN
#define BRAIN
namespace spiralcore {
class brain {
public:
@ -9,15 +16,26 @@ public:
// rewrites whole brain
void init(u32 block_size, u32 overlap);
// load, chop up and add to brain
// todo: add tags
sample load_sound(std::string filename);
// take another brain and rebuild this brain from bits of that one
// (presumably this one is made from a single sample)
sample resynth(const sample_brain *other, ratio);
sample resynth(const brain &other, float ratio);
static bool unit_test();
private:
vector<brain_block> m_blocks;
u32 search(const brain_block &target, float ratio);
void chop_and_add(const sample &s, u32 block_size, u32 overlap);
u32 m_block_size;
u32 m_overlap;
vector<brain_block> m_blocks;
vector<sample> m_samples;
};
#endif
}

View File

@ -1,19 +1,44 @@
#include <assert.h>
#include <iostream>
#include "libmfcc.h"
#include "brain_block.h"
using namespace spiralcore;
FFT *brain_block::m_fftw;
brain_block::brain_block(const sample &pcm) :
brain_block::brain_block(const string &filename, const sample &pcm, u32 rate) :
m_pcm(pcm),
m_fft(pcm.get_length()),
m_mfcc(13)
m_mfcc(13),
m_block_size(pcm.get_length()),
m_rate(rate),
m_orig_filename(filename)
{
init_fft(m_pcm.get_length());
m_fft = m_fftw(impulse2freq(m_pcm.get_non_const_buffer(),
m_fft.get_non_const_buffer())
for (u32 i=0; i<m_block_size; i++) {
// convert from float to double
m_fftw->m_in[i] = m_pcm[i];
}
m_fftw->raw_impulse2freq();
double *spectrum = new double[m_block_size];
for (u32 i=0; i<m_block_size; i++) {
// convert from complex to float for storage
m_fft[i] = m_fftw->m_spectrum[i][0];
// convert from complex to double for mfcc calc
spectrum[i] = m_fftw->m_spectrum[i][0];
}
for (u32 i=0; i<13; i++) {
m_mfcc[i] = GetCoefficient(spectrum, rate, 48, m_block_size, i);
}
delete[] spectrum;
}
void brain_block::init_fft(u32 block_size)
@ -23,3 +48,45 @@ void brain_block::init_fft(u32 block_size)
m_fftw = new FFT(block_size);
}
}
double brain_block::compare(const brain_block &other, float ratio) const {
double acc=0;
// just mfcc
//if (ratio==1)
{
for (u32 i=0; i<13; ++i) {
acc+=(m_mfcc[i]-other.m_mfcc[i]) * (m_mfcc[i]-other.m_mfcc[i]);
}
}
return acc;
}
bool brain_block::unit_test() {
sample data(20);
for (u32 i=0; i<data.get_length(); i++) {
data[i]=i/(float)data.get_length();
}
brain_block bb("test",data,44100);
assert(bb.m_pcm.get_length()==data.get_length());
assert(bb.m_fft.get_length()==data.get_length());
assert(bb.m_mfcc.get_length()==13);
assert(bb.m_orig_filename==string("test"));
assert(bb.m_rate==44100);
assert(bb.m_block_size==data.get_length());
brain_block bb2("test",data,44100);
assert(bb.compare(bb2,1)==0);
sample data2(20);
for (u32 i=0; i<data.get_length(); i++) {
data[i]=i;
}
brain_block bb3("test",data2,44100);
assert(bb.compare(bb3,1)!=0);
return true;
}

View File

@ -1,25 +1,36 @@
#include <vector>
#include <string>
#include "jellyfish/fluxa/sample.h"
#include "jellyfish/core/types.h"
#include "fft.h"
using namespace spiralcore;
#ifndef BRAIN_BLOCK
#define BRAIN_BLOCK
namespace spiralcore {
class brain_block {
public:
// runs analysis on pcm
brain_block(const sample &pcm);
brain_block(const std::string &filename, const sample &pcm, u32 rate);
// returns distance based on ratio of fft-mfcc values
float compare(const brain_block &other, float ratio);
double compare(const brain_block &other, float ratio) const;
static void init_fft(u32 block_size);
static bool unit_test();
private:
sample m_pcm;
sample m_fft;
sample m_mfcc;
u32 m_block_size;
u32 m_rate;
std::string m_orig_filename;
static FFT *m_fftw;
};
}
#endif

View File

@ -6,44 +6,20 @@
/* Define to 1 if you have the <iostream> header file. */
#undef HAVE_IOSTREAM
/* Define to 1 if you have the `bcm_host' library (-lbcm_host). */
#undef HAVE_LIBBCM_HOST
/* Define to 1 if you have the `fftw3' library (-lfftw3). */
#undef HAVE_LIBFFTW3
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the `EGL' library (-lEGL). */
#undef HAVE_LIBEGL
/* Define to 1 if you have the `GL' library (-lGL). */
#undef HAVE_LIBGL
/* Define to 1 if you have the `GLESv1_CM' library (-lGLESv1_CM). */
#undef HAVE_LIBGLESV1_CM
/* Define to 1 if you have the `glut' library (-lglut). */
#undef HAVE_LIBGLUT
/* Define to 1 if you have the `jpeg' library (-ljpeg). */
#undef HAVE_LIBJPEG
/* Define to 1 if you have the `lo' library (-llo). */
#undef HAVE_LIBLO
/* Define to 1 if you have the `jellyfish' library (-ljellyfish). */
#undef HAVE_LIBJELLYFISH
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the `png' library (-lpng). */
#undef HAVE_LIBPNG
/* Define to 1 if you have the `portaudio' library (-lportaudio). */
#undef HAVE_LIBPORTAUDIO
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have the `X11' library (-lX11). */
#undef HAVE_LIBX11
/* Define to 1 if you have the `sndfile' library (-lsndfile). */
#undef HAVE_LIBSNDFILE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H

View File

@ -1,5 +1,7 @@
#include <fft.h>
using namespace spiralcore;
static const int MAX_FFT_LENGTH = 4096;
FFT::FFT(int length) :
@ -52,3 +54,8 @@ void FFT::impulse2freq(float *imp, float *out)
out[i] = m_spectrum[i][0];
}
}
void FFT::raw_impulse2freq()
{
fftw_execute(m_plan);
}

View File

@ -1,13 +1,19 @@
#include <fftw3.h>
#ifndef SPIRALCORE_FFT
#define SPIRALCORE_FFT
//#define __FFTWFLOAT__
namespace spiralcore {
class FFT
{
public:
FFT(int length);
~FFT();
void impulse2freq(float *imp, float *out);
void raw_impulse2freq();
#ifndef __FFTWFLOAT__
fftw_plan m_plan;
@ -21,3 +27,7 @@ public:
fftwf_complex *m_spectrum;
#endif
};
}
#endif

View File

@ -20,9 +20,19 @@
#include "jellyfish/audio.h"
#include "brain_block.h"
#include "brain.h"
using namespace std;
int main(int argc, char *argv[])
{
audio_device *a = new audio_device("samplebrain",44100,2048);
cerr<<"testing brain_block"<<endl;
if (brain_block::unit_test()) cerr<<"passed"<<endl;
else cerr<<"failed"<<endl;
cerr<<"testing brain"<<endl;
if (brain::unit_test()) cerr<<"passed"<<endl;
else cerr<<"failed"<<endl;
//audio_device *a = new audio_device("samplebrain",44100,2048);
}