c-gaborator/cgaborator.cpp
2022-01-25 13:59:02 +01:00

125 lines
4.1 KiB
C++

#include <iostream>
#include "include/cgaborator.h"
#include "gaborator/gaborator.h"
#include <cmath>
const int C_ARRAY_SIZE = 300000 * 2;
struct GaboratorState {
gaborator::parameters* paramsRef;
gaborator::analyzer<float>* analyzerRef;
gaborator::coefs<float>* coefsRef;
int64_t t_in;
int min_band;
int sample_rate;
int64_t anal_support;
float cArray[C_ARRAY_SIZE];
};
void* gaborator_initialize(double sampleRate, int bandsPerOctave, double minimumFrequency, double maximumFrequency, double referenceFrequency){
auto state = new GaboratorState();
state->paramsRef = new gaborator::parameters(bandsPerOctave, minimumFrequency / sampleRate, referenceFrequency / sampleRate, 1.0, 1e-5);
state->analyzerRef = new gaborator::analyzer<float>(*(state->paramsRef));
state->coefsRef = new gaborator::coefs<float>(*(state->analyzerRef));
//converts frequency (ff_max) in hertz to the number of bands above the min frequency
//the ceil is used to end up at a full band
int interesting_bands = ceil(bandsPerOctave * log(maximumFrequency/minimumFrequency)/log(2.0f));
//since bands are ordered from high to low we are only interested in lower bands:
//fs/2.0 is the nyquist frequency
int total_bands = ceil(bandsPerOctave * log(sampleRate/2.0/minimumFrequency)/log(2.0f));
state->anal_support = (int64_t) ceil(state->analyzerRef->analysis_support());
state->min_band = total_bands - interesting_bands;
state->sample_rate = (int) sampleRate;
state->t_in = 0;
assert(state->t_in == 0);
return state;
}
long gaborator_get_anal_support(void* ptr) {
return reinterpret_cast<GaboratorState*>(ptr)->anal_support;
}
void gaborator_analyze(void* ptr, float* audio_block, int audio_block_length) {
auto state = reinterpret_cast<GaboratorState*>(ptr);
std::vector<float> buf(audio_block,audio_block + audio_block_length);
int output_index = 0;
state->analyzerRef->analyze(buf.data(), state->t_in, state->t_in + audio_block_length, *(state->coefsRef));
int64_t st0 = state->t_in - state->anal_support;
int64_t st1 = state->t_in - state->anal_support + audio_block_length;
apply(
*state->analyzerRef,
*state->coefsRef,
[&](std::complex<float> coef, int band, int64_t audioSampleIndex ) {
//ignores everything above the max_band
if(band >= state->min_band){
//printf("%f %d %ld\n",std::abs(coef),band,audioSampleIndex);
state->cArray[output_index++] = band;
state->cArray[output_index++] = audioSampleIndex;
state->cArray[output_index++] = std::abs(coef);
//printf("output_index: %d\n", output_index++);
//output_index++;
}
},st0,
st1);
state->t_in += (int64_t) audio_block_length;
int64_t t_out = state->t_in - state->anal_support;
forget_before(*state->analyzerRef, *state->coefsRef, t_out - audio_block_length);
}
float* gaborator_get_array(void* ptr) {
auto state = reinterpret_cast<GaboratorState*>(ptr);
return &state->cArray[0];
}
int gaborator_get_array_length(void* ptr) {
auto state = reinterpret_cast<GaboratorState*>(ptr);
return sizeof(state->cArray) / sizeof(state->cArray[0]);
}
int gaborator_bandcenters_array_length(void* ptr) {
auto state = reinterpret_cast<GaboratorState*>(ptr);
int max_band = state->analyzerRef->bandpass_bands_end();
return max_band+1;
}
void gaborator_bandcenters(void* ptr, float* band_centers) {
auto state = reinterpret_cast<GaboratorState*>(ptr);
int max_band = state->analyzerRef->bandpass_bands_end();
//band_centers = new float[max_band+1]; //TODO
for(int i = 0 ; i < max_band ; i++){
if(i<state->min_band){
band_centers[i]=-1;
}else{
band_centers[i]=state->analyzerRef->band_ff(i) * state->sample_rate;
}
}
}
void gaborator_release(void* ptr) {
auto state = reinterpret_cast<GaboratorState*>(ptr);
//cleanup memory
delete state->analyzerRef;
delete state->coefsRef;
delete state->paramsRef;
delete state;
}