demo readish

This commit is contained in:
Dave Griffiths 2015-07-09 22:59:44 +01:00
parent cb1ca8e0e3
commit 7d7c7c82f6
8 changed files with 62 additions and 52 deletions

View File

@ -4,14 +4,12 @@ TARGET_LIB := libsamplebrain.a
SRCS := src/fft.cpp \ SRCS := src/fft.cpp \
src/brain.cpp \ src/brain.cpp \
src/block.cpp \ src/block.cpp \
src/libmfcc.cpp \
src/main.cpp \ src/main.cpp \
src/mfcc.cpp \ src/mfcc.cpp \
src/renderer.cpp \ src/renderer.cpp \
src/aquila/filter/MelFilterBank.cpp \ src/aquila/filter/MelFilterBank.cpp \
src/aquila/filter/MelFilter.cpp \ src/aquila/filter/MelFilter.cpp \
src/aquila/transform/Dct.cpp \ src/aquila/transform/Dct.cpp \
src/renderer.cpp
TARGET_SRCS := src/main.cpp TARGET_SRCS := src/main.cpp

View File

@ -4,4 +4,4 @@ make distclean
autoheader autoheader
# build configure # build configure
autoconf configure.ac > configure autoconf configure.ac > configure
./configure CXX=g++-4.7 ./configure CXX=g++-4.7 CCFLAGS=-O3

View File

@ -1,7 +1,6 @@
#include <assert.h> #include <assert.h>
#include <iostream> #include <iostream>
#include "libmfcc.h"
#include "block.h" #include "block.h"
using namespace spiralcore; using namespace spiralcore;
@ -20,7 +19,7 @@ void enveloper(sample &s, u32 start, u32 end) {
} }
} }
block::block(const string &filename, const sample &pcm, u32 rate, bool ditchpcm) : block::block(const string &filename, const sample &pcm, u32 rate, u32 env, bool ditchpcm) :
m_pcm(pcm), m_pcm(pcm),
m_fft(pcm.get_length()), m_fft(pcm.get_length()),
m_mfcc(MFCC_FILTERS), m_mfcc(MFCC_FILTERS),
@ -32,7 +31,7 @@ block::block(const string &filename, const sample &pcm, u32 rate, bool ditchpcm)
assert(m_mfcc_proc!=NULL); assert(m_mfcc_proc!=NULL);
assert(m_fftw!=NULL); assert(m_fftw!=NULL);
enveloper(m_pcm,50,50); enveloper(m_pcm,env,env);
m_fftw->impulse2freq(m_pcm.get_non_const_buffer()); m_fftw->impulse2freq(m_pcm.get_non_const_buffer());
@ -104,7 +103,7 @@ bool block::unit_test() {
data[i]=i/(float)data.get_length(); data[i]=i/(float)data.get_length();
} }
block bb("test",data,44100); block bb("test",data,44100,0);
assert(bb.m_pcm.get_length()==data.get_length()); assert(bb.m_pcm.get_length()==data.get_length());
//assert(bb.m_fft.get_length()==data.get_length()); //assert(bb.m_fft.get_length()==data.get_length());
@ -113,7 +112,7 @@ bool block::unit_test() {
assert(bb.m_rate==44100); assert(bb.m_rate==44100);
assert(bb.m_block_size==data.get_length()); assert(bb.m_block_size==data.get_length());
block bb2("test",data,44100); block bb2("test",data,44100,0);
assert(bb.compare(bb2,1)==0); assert(bb.compare(bb2,1)==0);
assert(bb.compare(bb2,0)==0); assert(bb.compare(bb2,0)==0);
assert(bb.compare(bb2,0.5)==0); assert(bb.compare(bb2,0.5)==0);
@ -123,13 +122,13 @@ bool block::unit_test() {
data[i]=i%10; data[i]=i%10;
} }
block cpy("test",data,100); block cpy("test",data,100,4);
{ {
block bb3("test",data2,44100); block bb3("test",data2,44100,4);
assert(bb.compare(bb3,1)!=0); assert(bb.compare(bb3,1)!=0);
assert(bb.compare(bb3,0)!=0); assert(bb.compare(bb3,0)!=0);
assert(bb.compare(bb3,0.5)!=0); assert(bb.compare(bb3,0.5)!=0);
cpy=bb3; cpy=bb3;
} }
assert(cpy.m_pcm.get_length()==200); assert(cpy.m_pcm.get_length()==200);

View File

@ -12,7 +12,7 @@ namespace spiralcore {
class block { class block {
public: public:
// runs analysis on pcm // runs analysis on pcm
block(const std::string &filename, const sample &pcm, u32 rate, bool ditchpcm=false); block(const std::string &filename, const sample &pcm, u32 rate, u32 env, bool ditchpcm=false);
// returns distance based on ratio of fft-mfcc values // returns distance based on ratio of fft-mfcc values
double compare(const block &other, float ratio) const; double compare(const block &other, float ratio) const;

View File

@ -38,23 +38,23 @@ void save_sample(const string &filename, const sample s) {
} }
// rewrites whole brain // rewrites whole brain
void brain::init(u32 block_size, u32 overlap, bool ditchpcm) { void brain::init(u32 block_size, u32 overlap, u32 env, bool ditchpcm) {
m_blocks.clear(); m_blocks.clear();
m_block_size = block_size; m_block_size = block_size;
m_overlap = overlap; m_overlap = overlap;
for (vector<sample>::iterator i=m_samples.begin(); i!=m_samples.end(); ++i) { for (vector<sample>::iterator i=m_samples.begin(); i!=m_samples.end(); ++i) {
chop_and_add(*i, block_size, overlap, ditchpcm); chop_and_add(*i, block_size, overlap, env, ditchpcm);
} }
} }
void brain::chop_and_add(const sample &s, u32 block_size, u32 overlap, bool ditchpcm) { void brain::chop_and_add(const sample &s, u32 block_size, u32 overlap, u32 env, bool ditchpcm) {
u32 pos=0; u32 pos=0;
while (pos+block_size-1<s.get_length()) { while (pos+block_size-1<s.get_length()) {
cerr<<'\r'; cerr<<'\r';
cerr<<"adding: "<<pos/(float)s.get_length()*100; cerr<<"adding: "<<pos/(float)s.get_length()*100;
sample region; sample region;
s.get_region(region,pos,pos+block_size-1); s.get_region(region,pos,pos+block_size-1);
m_blocks.push_back(block("",region,44100,ditchpcm)); m_blocks.push_back(block("",region,44100,env,ditchpcm));
pos += (block_size-overlap); pos += (block_size-overlap);
} }
} }
@ -123,13 +123,13 @@ bool brain::unit_test() {
assert(b.m_samples.size()==2); assert(b.m_samples.size()==2);
assert(s.get_length()==100); assert(s.get_length()==100);
b.init(10, 0); b.init(10, 0, 0);
assert(b.m_samples.size()==2); assert(b.m_samples.size()==2);
assert(b.m_blocks.size()==20); assert(b.m_blocks.size()==20);
b.init(10, 5); b.init(10, 5, 0);
assert(b.m_samples.size()==2); assert(b.m_samples.size()==2);
assert(b.m_blocks.size()==38); assert(b.m_blocks.size()==38);
b.init(20, 5); b.init(20, 5, 0);
assert(b.m_samples.size()==2); assert(b.m_samples.size()==2);
assert(b.m_blocks.size()==12); assert(b.m_blocks.size()==12);
@ -139,8 +139,8 @@ bool brain::unit_test() {
brain b3; brain b3;
b3.load_sound("test_data/up.wav"); b3.load_sound("test_data/up.wav");
b2.init(512, 0); b2.init(512, 0, 20);
b3.init(512, 0); b3.init(512, 0, 20);
assert(b3.search(b2.m_blocks[0],1)==0); assert(b3.search(b2.m_blocks[0],1)==0);
assert(b3.search(b2.m_blocks[9],1)==9); assert(b3.search(b2.m_blocks[9],1)==9);
assert(b3.search(b2.m_blocks[19],1)==19); assert(b3.search(b2.m_blocks[19],1)==19);

View File

@ -14,7 +14,7 @@ public:
brain(); brain();
// rewrites whole brain // rewrites whole brain
void init(u32 block_size, u32 overlap, bool ditchpcm=false); void init(u32 block_size, u32 overlap, u32 env, bool ditchpcm=false);
// load, chop up and add to brain // load, chop up and add to brain
// todo: add tags // todo: add tags
@ -25,6 +25,7 @@ public:
const sample &get_block_pcm(u32 index) const; const sample &get_block_pcm(u32 index) const;
const block &get_block(u32 index) const; const block &get_block(u32 index) const;
const u32 get_num_blocks() const { return m_blocks.size(); }
const u32 get_block_size() const { return m_block_size; } const u32 get_block_size() const { return m_block_size; }
const u32 get_overlap() const { return m_overlap; } const u32 get_overlap() const { return m_overlap; }
@ -34,7 +35,7 @@ public:
private: private:
void chop_and_add(const sample &s, u32 block_size, u32 overlap, bool ditchpcm=false); void chop_and_add(const sample &s, u32 block_size, u32 overlap, u32 env, bool ditchpcm=false);
vector<block> m_blocks; vector<block> m_blocks;
vector<sample> m_samples; vector<sample> m_samples;

View File

@ -53,20 +53,21 @@ void run_audio(void* c, unsigned int frames) {
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// unit_test(); unit_test();
cerr<<"starting"<<endl; cerr<<"starting"<<endl;
brain source, target; brain source, target;
source.load_sound("../sound/source/shostakovich6.wav"); // 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/full.wav");
target.load_sound("../sound/source/sb-left.wav");
// target.load_sound("../sound/source/sb-left.wav"); // target.load_sound("../sound/source/sb-left.wav");
target.load_sound("../sound/source/apache.wav");
cerr<<"loaded sounds"<<endl; cerr<<"loaded sounds"<<endl;
u32 len=3000; u32 len=1024;
source.init(len,len-len); source.init(len,len-len,50);
target.init(len,len-len/2); target.init(len,len-len/4,50);
cerr<<"ready..."<<endl; cerr<<"ready..."<<endl;
a = new audio_device("samplebrain",44100,2048); a = new audio_device("samplebrain",44100,2048);

View File

@ -14,15 +14,23 @@ void renderer::init(brain &source, brain &target, float ratio) {
void renderer::process(u32 nframes, float *buf) { void renderer::process(u32 nframes, float *buf) {
// get blocks from source for the current buffer // get blocks from source for the current buffer
u32 src_shift = m_source.get_block_size()-m_source.get_overlap();
u32 tgt_shift = m_target.get_block_size()-m_target.get_overlap(); u32 tgt_shift = m_target.get_block_size()-m_target.get_overlap();
u32 tgt_start = m_render_time/(float)tgt_shift; u32 tgt_start = m_render_time/(float)tgt_shift;
u32 tgt_end = (m_render_time+nframes)/(float)tgt_shift; u32 tgt_end = (m_render_time+nframes)/(float)tgt_shift;
tgt_end++;
if (tgt_end>=m_target.get_num_blocks()) {
m_render_time=0;
m_render_blocks.clear();
// next time...
return;
}
// cerr<<"-----------------"<<endl;
// cerr<<"tgt start:"<<tgt_start<<endl;
// cerr<<"tgt end:"<<tgt_end<<endl;
// get indices for current buffer // get indices for current buffer
for (u32 tgt_index = tgt_start; tgt_index<tgt_end; tgt_index++) { for (u32 tgt_index = tgt_start; tgt_index<=tgt_end; tgt_index++) {
u32 time=tgt_index*tgt_shift; u32 time=tgt_index*tgt_shift;
u32 src_index = m_source.search(m_target.get_block(tgt_index), m_ratio); u32 src_index = m_source.search(m_target.get_block(tgt_index), m_ratio);
// put them in the index list // put them in the index list
@ -36,24 +44,27 @@ void renderer::process(u32 nframes, float *buf) {
s32 offset = i->m_time-m_render_time; s32 offset = i->m_time-m_render_time;
// assume midway through block // assume midway through block
s32 block_start = offset; u32 block_start = offset;
u32 buffer_start = 0; u32 buffer_start = 0;
if (block_start<0) { if (offset<0) {
block_start=-block_start; block_start=-offset;
if (block_start>=pcm.get_length()) i->m_finished=true; if (block_start>=pcm.get_length()) i->m_finished=true;
} else { // block is midway through buffer } else { // block is midway through buffer
block_start=0; block_start=0;
buffer_start=offset; buffer_start=offset;
} }
// cerr<<"-----------------"<<endl;
// cerr<<"block start:"<<block_start<<endl;
// cerr<<"buffer start:"<<buffer_start<<endl;
if (!i->m_finished) { if (!i->m_finished) {
// mix in // mix in
u32 buffer_pos = buffer_start; u32 buffer_pos = buffer_start;
u32 block_pos = block_start; u32 block_pos = block_start;
u32 block_end = block_start+pcm.get_length(); u32 block_end = pcm.get_length();
while (block_pos<block_end && buffer_pos<nframes) { while (block_pos<block_end && buffer_pos<nframes) {
buf[buffer_pos]+=pcm[block_pos]; buf[buffer_pos]+=pcm[block_pos]*0.2;
++buffer_pos; ++buffer_pos;
++block_pos; ++block_pos;
} }
@ -75,26 +86,26 @@ void renderer::process(u32 nframes, float *buf) {
bool renderer::unit_test() { bool renderer::unit_test() {
brain source; brain source;
source.load_sound("test_data/up.wav"); source.load_sound("test_data/up.wav");
source.init(10,0); source.init(10,0,0);
brain target; brain target;
target.load_sound("test_data/up.wav"); target.load_sound("test_data/up.wav");
target.init(10,0); target.init(10,0,0);
renderer rr(source,target,1); renderer rr(source,target,1);
float *buf=new float[10]; float *buf=new float[10];
rr.process(5,buf);
assert(rr.m_render_blocks.size()==1);
rr.process(10,buf); rr.process(10,buf);
assert(rr.m_render_blocks.size()==1);
rr.process(20,buf);
assert(rr.m_render_blocks.size()==2); assert(rr.m_render_blocks.size()==2);
rr.process(5,buf);
assert(rr.m_render_blocks.size()==1);
target.init(10,5);
rr.process(10,buf); rr.process(10,buf);
assert(rr.m_render_blocks.size()==3);
rr.process(20,buf);
assert(rr.m_render_blocks.size()==4); assert(rr.m_render_blocks.size()==4);
rr.process(5,buf);
assert(rr.m_render_blocks.size()==2);
target.init(10,5,0);
rr.process(10,buf);
assert(rr.m_render_blocks.size()==5);
} }