From cb1ca8e0e3632e1c9fd4a231b01302fe679b024e Mon Sep 17 00:00:00 2001 From: Dave Griffiths Date: Thu, 9 Jul 2015 21:50:03 +0100 Subject: [PATCH] rename + missing --- samplebrain/src/block.cpp | 138 +++++++++++++++++++++++++++++++++++ samplebrain/src/block.h | 40 ++++++++++ samplebrain/src/mfcc.cpp | 35 +++++++++ samplebrain/src/mfcc.h | 82 +++++++++++++++++++++ samplebrain/src/renderer.cpp | 100 +++++++++++++++++++++++++ samplebrain/src/renderer.h | 38 ++++++++++ 6 files changed, 433 insertions(+) create mode 100644 samplebrain/src/block.cpp create mode 100644 samplebrain/src/block.h create mode 100644 samplebrain/src/mfcc.cpp create mode 100644 samplebrain/src/mfcc.h create mode 100644 samplebrain/src/renderer.cpp create mode 100644 samplebrain/src/renderer.h diff --git a/samplebrain/src/block.cpp b/samplebrain/src/block.cpp new file mode 100644 index 0000000..7258149 --- /dev/null +++ b/samplebrain/src/block.cpp @@ -0,0 +1,138 @@ +#include +#include + +#include "libmfcc.h" +#include "block.h" + +using namespace spiralcore; + +FFT *block::m_fftw; +Aquila::Mfcc *block::m_mfcc_proc; + +static const int MFCC_FILTERS=12; + +void enveloper(sample &s, u32 start, u32 end) { + for(u32 i=0; iimpulse2freq(m_pcm.get_non_const_buffer()); + + std::vector> mfspec; + + for (u32 i=0; im_spectrum[i][0]; + + mfspec.push_back(std::complex(m_fftw->m_spectrum[i][0], + m_fftw->m_spectrum[i][1])); + } + + if (m_block_size>100) m_fft.crop_to(100); + if (ditchpcm) m_pcm.clear(); + + // calculate mfcc + std::vector m = m_mfcc_proc->calculate(mfspec,MFCC_FILTERS); + + for (u32 i=0; im_length!=block_size) { + if (m_fftw == NULL) delete m_fftw; + m_fftw = new FFT(block_size); + if (m_mfcc_proc == NULL) delete m_mfcc_proc; + m_mfcc_proc = new Aquila::Mfcc(block_size); + } +} + +double block::compare(const block &other, float ratio) const { + double mfcc_acc=0; + double fft_acc=0; + + if (ratio==0) { + for (u32 i=0; i +#include "jellyfish/fluxa/sample.h" +#include "jellyfish/core/types.h" +#include "fft.h" +#include "mfcc.h" + +#ifndef BLOCK +#define BLOCK + +namespace spiralcore { + +class block { +public: + // runs analysis on pcm + block(const std::string &filename, const sample &pcm, u32 rate, bool ditchpcm=false); + + // returns distance based on ratio of fft-mfcc values + double compare(const block &other, float ratio) const; + + static void init_fft(u32 block_size); + static bool unit_test(); + + const sample &get_pcm() const { return m_pcm; } + +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; + static Aquila::Mfcc *m_mfcc_proc; + +}; + +} + +#endif diff --git a/samplebrain/src/mfcc.cpp b/samplebrain/src/mfcc.cpp new file mode 100644 index 0000000..55014f6 --- /dev/null +++ b/samplebrain/src/mfcc.cpp @@ -0,0 +1,35 @@ +/** + * @file Mfcc.cpp + * + * Calculation of MFCC signal features. + * + * This file is part of the Aquila DSP library. + * Aquila is free software, licensed under the MIT/X11 License. A copy of + * the license is provided with the library in the LICENSE file. + * + * @package Aquila + * @version 3.0.0-dev + * @author Zbigniew Siciarz + * @date 2007-2014 + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @since 3.0.0 + */ + +#include "mfcc.h" +#include "aquila/transform/Dct.h" +#include "aquila/filter/MelFilterBank.h" + +namespace Aquila +{ + std::vector Mfcc::calculate(SpectrumType spectrum, + std::size_t numFeatures) + { + //auto spectrum = m_fft->fft(source); + + Aquila::MelFilterBank bank(44100, m_inputSize); + auto filterOutput = bank.applyAll(spectrum); + + Aquila::Dct dct; + return dct.dct(filterOutput, numFeatures); + } +} diff --git a/samplebrain/src/mfcc.h b/samplebrain/src/mfcc.h new file mode 100644 index 0000000..a4b2682 --- /dev/null +++ b/samplebrain/src/mfcc.h @@ -0,0 +1,82 @@ +/** + * @file Mfcc.h + * + * Calculation of MFCC signal features. + * + * This file is part of the Aquila DSP library. + * Aquila is free software, licensed under the MIT/X11 License. A copy of + * the license is provided with the library in the LICENSE file. + * + * @package Aquila + * @version 3.0.0-dev + * @author Zbigniew Siciarz + * @date 2007-2014 + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @since 3.0.0 + */ + +#ifndef MFCC_H +#define MFCC_H + +#include "aquila/global.h" +#include "aquila/transform/FftFactory.h" +#include +#include +#include + +namespace Aquila +{ + + /** + * The Mfcc class implements calculation of MFCC features from input signal. + * + * MFCC coefficients are commonly used in speech recognition. The common + * workflow is to split input signal in frames of equal length and apply + * MFCC calculation to each frame individually. Hence a few assumptions + * were made here: + * + * - a single Mfcc instance can be used only to process signals of equal + * length, for example consecutive frames + * - if you need to handle signals of various lengths, just create new + * Mfcc object per each signal source + * + * The code below is a simplest possible example of how to calculate MFCC + * for each frame of input signal. + * + * FramesCollection frames(data, FRAME_SIZE); + * Mfcc mfcc(FRAME_SIZE); + * for (Frame& frame : frames) { + * auto mfccValues = mfcc.calculate(frame); + * // do something with the calculated values + * } + * + */ + class AQUILA_EXPORT Mfcc + { + public: + /** + * Constructor creates the FFT object to reuse between calculations. + * + * @param inputSize input length (common to all inputs) + */ + Mfcc(std::size_t inputSize): + m_inputSize(inputSize)//, m_fft(FftFactory::getFft(inputSize)) + { + } + + std::vector calculate(SpectrumType s, std::size_t numFeatures = 12); + + private: + /** + * Number of samples in each processed input. + */ + const std::size_t m_inputSize; + + /** + * FFT calculator. + */ + //std::shared_ptr m_fft; + }; +} + +#endif // MFCC_H diff --git a/samplebrain/src/renderer.cpp b/samplebrain/src/renderer.cpp new file mode 100644 index 0000000..20444be --- /dev/null +++ b/samplebrain/src/renderer.cpp @@ -0,0 +1,100 @@ +#include "renderer.h" +#include + +using namespace spiralcore; +using namespace std; + +void renderer::init(brain &source, brain &target, float ratio) { + m_source=source; + m_target=target; + m_render_time=0; + m_render_blocks.clear(); + m_ratio = ratio; +} + +void renderer::process(u32 nframes, float *buf) { + // 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_start = m_render_time/(float)tgt_shift; + u32 tgt_end = (m_render_time+nframes)/(float)tgt_shift; + tgt_end++; + + // get indices for current buffer + for (u32 tgt_index = tgt_start; tgt_index::iterator i=m_render_blocks.begin(); i!=m_render_blocks.end(); ++i) { + const sample &pcm=m_source.get_block_pcm(i->m_index); + // get the sample offset into the buffer + s32 offset = i->m_time-m_render_time; + + // assume midway through block + s32 block_start = offset; + u32 buffer_start = 0; + if (block_start<0) { + block_start=-block_start; + if (block_start>=pcm.get_length()) i->m_finished=true; + } else { // block is midway through buffer + block_start=0; + buffer_start=offset; + } + + + if (!i->m_finished) { + // mix in + u32 buffer_pos = buffer_start; + u32 block_pos = block_start; + u32 block_end = block_start+pcm.get_length(); + while (block_pos::iterator i=m_render_blocks.begin(); + std::list::iterator ni=m_render_blocks.begin(); + while(i!=m_render_blocks.end()) { + ni++; + if (i->m_finished) m_render_blocks.erase(i); + i=ni; + } + + m_render_time+=nframes; +} + +bool renderer::unit_test() { + brain source; + source.load_sound("test_data/up.wav"); + source.init(10,0); + + brain target; + target.load_sound("test_data/up.wav"); + target.init(10,0); + + renderer rr(source,target,1); + float *buf=new float[10]; + rr.process(5,buf); + assert(rr.m_render_blocks.size()==1); + rr.process(10,buf); + assert(rr.m_render_blocks.size()==1); + rr.process(20,buf); + 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); + assert(rr.m_render_blocks.size()==4); + + +} diff --git a/samplebrain/src/renderer.h b/samplebrain/src/renderer.h new file mode 100644 index 0000000..683f469 --- /dev/null +++ b/samplebrain/src/renderer.h @@ -0,0 +1,38 @@ +#include +#include +#include "brain.h" + +namespace spiralcore { + +class renderer { +public: + renderer(brain &source, brain &target, float ratio) : + m_source(source), m_target(target) + { init(source,target,ratio); } + + void init(brain &source, brain &target, float ratio); + void process(u32 nframes, float *buf); + + static bool unit_test(); + +private: + + // realtime stuff + class render_block { + public: + render_block(u32 index, u32 time) : + m_index(index), m_time(time), m_finished(false) {} + u32 m_index; + u32 m_time; // in samples + bool m_finished; + }; + + brain &m_source; + brain &m_target; + float m_ratio; + + std::list m_render_blocks; + u32 m_render_time; +}; + +}