Now working with the new structure of fluid_decompositon - commit ebad604
parent
8091851198
commit
3936a42b51
@ -1,100 +0,0 @@
|
|||||||
#include "fluid_client_nmf.h"
|
|
||||||
#include "STFT.hpp"
|
|
||||||
#include "RatioMask.hpp"
|
|
||||||
|
|
||||||
namespace fluid{
|
|
||||||
namespace nmf{
|
|
||||||
using fluid::nmf::NMF;
|
|
||||||
using fluid::stft::STFT;
|
|
||||||
using fluid::stft::ISTFT;
|
|
||||||
using fluid::stft::Spectrogram;
|
|
||||||
using fluid::FluidTensor;
|
|
||||||
|
|
||||||
|
|
||||||
NMFClient::NMFClient(size_t rank,size_t iterations, size_t fft_size, size_t window_size, size_t hop_size):
|
|
||||||
m_rank(rank),m_iterations(iterations), m_fft_size(fft_size), m_window_size(window_size), m_hop_size(hop_size), m_has_processed(false), m_has_resynthed(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
void NMFClient::process(const FluidTensor<double, 1> &data, bool resynthesise)
|
|
||||||
{
|
|
||||||
m_audio_buffers.resize(m_rank,data.extent(0));
|
|
||||||
|
|
||||||
m_has_processed = false;
|
|
||||||
m_has_resynthed = false;
|
|
||||||
STFT stft(m_window_size,m_fft_size,m_hop_size);
|
|
||||||
Spectrogram spec = stft.process(data);
|
|
||||||
FluidTensor<double, 2> mag = spec.getMagnitude();
|
|
||||||
NMF nmf(m_rank,m_iterations);
|
|
||||||
m_model = nmf.process(spec.getMagnitude());
|
|
||||||
m_has_processed = true;
|
|
||||||
|
|
||||||
if(resynthesise)
|
|
||||||
{
|
|
||||||
ratiomask::RatioMask mask(m_model.getMixEstimate(),1);
|
|
||||||
ISTFT istft(m_window_size, m_fft_size, m_hop_size);
|
|
||||||
for(int i = 0; i < m_rank; ++i)
|
|
||||||
{
|
|
||||||
RealMatrix estimate = m_model.getEstimate(i);
|
|
||||||
Spectrogram result(mask.process(spec.mData, estimate));
|
|
||||||
RealVector audio = istft.process(result);
|
|
||||||
m_audio_buffers.row(i) = audio;
|
|
||||||
}
|
|
||||||
m_has_resynthed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t NMFClient::dictionary_size() const
|
|
||||||
{
|
|
||||||
return m_has_processed ? m_model.getW().extent(0) : 0 ;
|
|
||||||
}
|
|
||||||
size_t NMFClient::activations_length() const{
|
|
||||||
return m_has_processed ? m_model.getH().extent(1) : 0;
|
|
||||||
}
|
|
||||||
size_t NMFClient::num_sources() const
|
|
||||||
{
|
|
||||||
return m_has_resynthed ? m_audio_buffers.size() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FluidTensorView<double, 1> NMFClient::dictionary(const size_t idx) const
|
|
||||||
{
|
|
||||||
assert(m_has_processed && idx < m_model.W.cols());
|
|
||||||
return m_model.getW().col(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FluidTensorView<double, 1> NMFClient::activation(const size_t idx) const
|
|
||||||
{
|
|
||||||
assert(m_has_processed && idx < m_model.H.rows());
|
|
||||||
return m_model.getH().row(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FluidTensor<double,2> NMFClient::dictionaries() const
|
|
||||||
{
|
|
||||||
return m_model.getW();
|
|
||||||
}
|
|
||||||
const FluidTensor<double,2> NMFClient::activations()const
|
|
||||||
{
|
|
||||||
return m_model.getH();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const FluidTensorView<double, 1> NMFClient::source(const size_t idx) const
|
|
||||||
{
|
|
||||||
assert(idx < m_audio_buffers.rows() && "Range Error");
|
|
||||||
return m_audio_buffers.row(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// source_iterator NMFClient::sources_begin() const
|
|
||||||
// {
|
|
||||||
// return m_audio_buffers.cbegin();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// source_iterator NMFClient::sources_end() const
|
|
||||||
// {
|
|
||||||
// return m_audio_buffers.cend();
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
}//namespace nmf
|
|
||||||
}//namespace fluid
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "FluidTensor.hpp"
|
|
||||||
#include "NMF.hpp"
|
|
||||||
#include <vector>
|
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
using fluid::FluidTensor;
|
|
||||||
|
|
||||||
namespace fluid {
|
|
||||||
namespace nmf{
|
|
||||||
/**
|
|
||||||
Integration class for doing NMF filtering and resynthesis
|
|
||||||
**/
|
|
||||||
class NMFClient
|
|
||||||
{
|
|
||||||
// using vec_iterator = std::vector<double>::const_iterator;
|
|
||||||
// using source_iterator = std::vector<std::vector<double>>::const_iterator;
|
|
||||||
|
|
||||||
public:
|
|
||||||
//No, you may not construct an empty instance, or copy this, or move this
|
|
||||||
NMFClient() = delete;
|
|
||||||
NMFClient(NMFClient&)=delete;
|
|
||||||
NMFClient(NMFClient&&)=delete;
|
|
||||||
NMFClient operator=(NMFClient&)=delete;
|
|
||||||
NMFClient operator=(NMFClient&&)=delete;
|
|
||||||
|
|
||||||
/**
|
|
||||||
You may constrct one by supplying some senisble numbers here
|
|
||||||
rank: NMF rank
|
|
||||||
iterations: max nmf iterations
|
|
||||||
fft_size: power 2 pls
|
|
||||||
**/
|
|
||||||
NMFClient(size_t rank, size_t iterations, size_t fft_size, size_t window_size, size_t hop_size);
|
|
||||||
~NMFClient()= default;
|
|
||||||
//Not implemented
|
|
||||||
//void reset();
|
|
||||||
//bool isReady() const;
|
|
||||||
|
|
||||||
/***
|
|
||||||
Take some data, NMF it
|
|
||||||
***/
|
|
||||||
void process(const FluidTensor<double,1> &data, bool resynthesise);
|
|
||||||
|
|
||||||
/***
|
|
||||||
Report the size of a dictionary, in bins (= fft_size/2)
|
|
||||||
***/
|
|
||||||
size_t dictionary_size() const;
|
|
||||||
|
|
||||||
/***
|
|
||||||
Report the length of an activation, in frames
|
|
||||||
***/
|
|
||||||
size_t activations_length() const;
|
|
||||||
|
|
||||||
/***
|
|
||||||
Report the number of sources (i.e. the rank
|
|
||||||
***/
|
|
||||||
size_t num_sources() const;
|
|
||||||
// size_t rank() const;
|
|
||||||
|
|
||||||
/***
|
|
||||||
Retreive the dictionary at the given index
|
|
||||||
***/
|
|
||||||
const FluidTensorView<double, 1> dictionary(const size_t idx) const;
|
|
||||||
|
|
||||||
/***
|
|
||||||
Retreive the activation at the given index
|
|
||||||
***/
|
|
||||||
const FluidTensorView<double, 1> activation(const size_t idx) const;
|
|
||||||
|
|
||||||
/***
|
|
||||||
Retreive the resynthesized source at the given index (so long as resyntheiss has happened, mind
|
|
||||||
***/
|
|
||||||
const FluidTensorView<double, 1> source(const size_t idx) const;
|
|
||||||
|
|
||||||
// source_iterator sources_begin() const ;
|
|
||||||
// source_iterator sources_end()const;
|
|
||||||
|
|
||||||
/***
|
|
||||||
Get the whole of dictionaries / activations as a 2D structure
|
|
||||||
***/
|
|
||||||
const FluidTensor<double,2> dictionaries() const;
|
|
||||||
const FluidTensor<double,2> activations() const;
|
|
||||||
private:
|
|
||||||
size_t m_rank;
|
|
||||||
size_t m_iterations;
|
|
||||||
size_t m_fft_size;
|
|
||||||
size_t m_window_size;
|
|
||||||
size_t m_hop_size;
|
|
||||||
bool m_has_processed;
|
|
||||||
bool m_has_resynthed;
|
|
||||||
fluid::nmf::NMFModel m_model;
|
|
||||||
FluidTensor<double,2> m_audio_buffers;
|
|
||||||
};
|
|
||||||
} //namespace max
|
|
||||||
} //namesapce fluid
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
//
|
|
||||||
// fluid_nmf_tilde_util.h
|
|
||||||
// fluid.nmf~
|
|
||||||
//
|
|
||||||
// Created by Owen Green on 02/07/2018.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef fluid_nmf_tilde_util_h
|
|
||||||
#define fluid_nmf_tilde_util_h
|
|
||||||
|
|
||||||
#include "FluidTensor.hpp"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
namespace fluid{
|
|
||||||
namespace nmf{
|
|
||||||
|
|
||||||
using real_matrix = fluid::FluidTensor<double,2>;
|
|
||||||
|
|
||||||
struct error_strings
|
|
||||||
{
|
|
||||||
static constexpr const char* rank_below_one = "Rank < 1 makes no sense";
|
|
||||||
static constexpr const char* no_input_buffer_symbol = "Could not extract symbol from input buffer name";
|
|
||||||
static constexpr const char* no_out_polybuf_symbol = "Could not extract symbol from output polybuffer name";
|
|
||||||
|
|
||||||
static constexpr const char* sources_args = "At least three arguments required: NMF rank, input buffer, and output polybuffer.";
|
|
||||||
|
|
||||||
static constexpr const char* filters_args = "At least four arguments required: NMF rank, input buffer, output dictionary polybuffer, and output activations polybuffer.";
|
|
||||||
|
|
||||||
static constexpr const char* no_filter_polybuf_symbol = "Could not extract symbol from filters polybuffer name";
|
|
||||||
static constexpr const char* no_env_polybuf_symbol = "Could not extract symbol from envelopes polybuffer name";
|
|
||||||
static constexpr const char* get_buffer_fail = "Could not get buffer for name %s";
|
|
||||||
|
|
||||||
private:
|
|
||||||
error_strings(){}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// /*****************
|
|
||||||
// A template function to reduce duplication in copying back to Max buffers
|
|
||||||
// My hope is to render this either obsolete or much simpler once algo code
|
|
||||||
// is refactored.
|
|
||||||
// At present it needs to be fed a vector of vectors (ugh) and a function that
|
|
||||||
// does the copying (see under)
|
|
||||||
// *******************/
|
|
||||||
// template<typename F>
|
|
||||||
// void copy_to_buffer(t_object* obj, int rank, t_symbol* polybuf_name,real_matrix &mtrx,F&& copy_fn, double scale=1.)
|
|
||||||
// {
|
|
||||||
// for(int i = 0; i < rank; i++)
|
|
||||||
// {
|
|
||||||
// std::ostringstream ss;
|
|
||||||
// ss << polybuf_name->s_name << "." << i+1;
|
|
||||||
// const char* buffername = ss.str().c_str();
|
|
||||||
//
|
|
||||||
// t_buffer_ref* ref = buffer_ref_new(obj, gensym(buffername));
|
|
||||||
// t_buffer_obj* this_buffer = buffer_ref_getobject(ref);
|
|
||||||
//
|
|
||||||
// if(this_buffer)
|
|
||||||
// {
|
|
||||||
// float* samps = buffer_locksamples(this_buffer);
|
|
||||||
// if(samps)
|
|
||||||
// {
|
|
||||||
// copy_fn(samps,mtrx,i,scale);
|
|
||||||
// buffer_unlocksamples(this_buffer);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if(ref)
|
|
||||||
// object_free(ref);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void from_cols(float* dst, real_matrix &m, long i,double scale)
|
|
||||||
// {
|
|
||||||
// for(long j = 0; j< m[0].size(); j++)
|
|
||||||
// dst[j] = m[i][j] * scale;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void from_rows(float* dst,real_matrix &m, long i,double scale)
|
|
||||||
// {
|
|
||||||
// for(long j = 0; j < m.size(); j++)
|
|
||||||
// dst[j] = m[j][i] * scale;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* fluid_nmf_tilde_util_h */
|
|
||||||
Loading…
Reference in New Issue