block size independent output

This commit is contained in:
DataHoarder 2022-01-30 03:52:21 +01:00
parent 636476a226
commit d524cd1909
2 changed files with 93 additions and 74 deletions

View file

@ -8,11 +8,13 @@
class Gaborator {
public:
Gaborator(int blockSize, double sampleRate, int bandsPerOctave, double minimumFrequency, double referenceFrequency, double maximumFrequency, int stepSize) :
Gaborator(int block_size, double sampleRate, int bandsPerOctave, double minimumFrequency, double referenceFrequency, double maximumFrequency, int stepSize) :
parameters(bandsPerOctave, minimumFrequency / sampleRate, referenceFrequency / sampleRate, 1.0, 1e-5),
analyzer(parameters),
coefs(analyzer),
frequencyBinTimeStepSize(stepSize)
frequencyBinTimeStepSize(stepSize),
sample_rate((int) sampleRate),
blockSize(block_size)
{
//converts frequency (ff_max) in hertz to the number of bands above the min frequency
@ -25,7 +27,6 @@ public:
latency = (int64_t) ceil(analyzer.analysis_support());
min_band = total_bands - interesting_bands;
sample_rate = (int) sampleRate;
t_in = 0;
int max_band = analyzer.bandpass_bands_end();
@ -58,66 +59,12 @@ public:
}
void analyze(float* audio_block, int audio_block_length){
if (audio_block == nullptr) {
return;
}
analyzer.analyze(audio_block, t_in, t_in + audio_block_length, coefs);
int64_t st0 = t_in - latency;
int64_t st1 = t_in - latency + audio_block_length;
analysisVector.clear();
apply(
analyzer,
coefs,
[&](std::complex<float> coef, int band, int64_t audioSampleIndex ) {
//ignores everything above the max_band
if(band >= min_band){
analysisVector.push_back({band, static_cast<int>(audioSampleIndex), std::abs(coef)});
}
},st0,
st1);
t_in += (int64_t) audio_block_length;
int64_t t_out = t_in - latency;
forget_before(analyzer, coefs, t_out - audio_block_length);
}
void gabor_transform(float* audio_block, int audio_block_length, gaborator_transform_callback callback, uintptr_t callback_data) {
analyze(audio_block, audio_block_length);
for (auto& entry : analysisVector) {
int coefficientIndex = entry.sampleIndex / frequencyBinTimeStepSize;
int bandIndex = entry.bandIndex - firstBandCache;
int circularIndex = coefficientIndex % int(coefficients.size());
// The first results have a negative audio sample index
// ignore these
if (coefficientIndex > 0 && bandIndex < coefficients[circularIndex]->size()) {
// If a new index is reached, save the old (fixed) coefficients in the history
// Fill the array with zeros to get the max
if (coefficientIndex > mostRecentCoefficentIndex && coefficientIndex > coefficients.size()) {
// keep the new maximum
mostRecentCoefficentIndex = coefficientIndex;
// "copy" the oldest data to the history
// the slice can be reused thanks to the oldest being filled with zeros just after
callback(callback_data, coefficients[circularIndex]->data(), coefficients[circularIndex]->size());
// fill the oldest with zeros
//coefficients[circularIndex] = std::make_unique<std::vector<float>>(numberOfBandsCache)
std::fill(coefficients[circularIndex]->begin(), coefficients[circularIndex]->end(), 0);
}
// due to reduction in precision (from audio sample accuracy to steps) multiple
// magnitudes could be placed in the same stepIndex, bandIndex pair.
// We take the maximum magnitudes value.
(*coefficients[circularIndex])[bandIndex] = std::max((*coefficients[circularIndex])[bandIndex], entry.magnitude);
}
if (audio_block == nullptr || audio_block_length == 0) { //finish
finish(callback, callback_data);
} else {
analyze(audio_block, audio_block_length, callback, callback_data);
}
}
@ -131,23 +78,90 @@ public:
~Gaborator()= default;
private:
struct gaborator_analyze_entry {
int bandIndex;
int sampleIndex;
float magnitude;
};
std::vector<struct gaborator_analyze_entry> analysisVector;
private:
void analyze(float* audio_block, int audio_block_length, gaborator_transform_callback callback, uintptr_t callback_data){
analyzer.analyze(audio_block, t_in, t_in + audio_block_length, coefs);
int64_t st0 = t_in - latency;
int64_t st1 = t_in - latency + audio_block_length;
gaborator::process([&](int band, int64_t audioSampleIndex, std::complex<float>& coef) {
gabor_process_entry(band, int(audioSampleIndex), coef, callback, callback_data);
}, min_band, INT_MAX, st0, st1, coefs);
t_in += (int64_t) audio_block_length;
int64_t t_out = t_in - latency;
forget_before(analyzer, coefs, t_out - audio_block_length);
}
void finish(gaborator_transform_callback callback, uintptr_t callback_data){
int64_t st0 = t_in - latency;
int64_t st1 = t_in;
//flush all till latency spot
gaborator::process([&](int band, int64_t audioSampleIndex, std::complex<float>& coef) {
gabor_process_entry(band, int(audioSampleIndex), coef, callback, callback_data);
}, min_band, INT_MAX, st0, st1, coefs);
//flush remaining
for (int i = 1; i < coefficientSize; ++i) {
int circularIndex = (mostRecentCoefficentIndex + i) % int(coefficientSize);
auto& currentCoefficient = *coefficients[circularIndex];
callback(callback_data, currentCoefficient.data(), static_cast<int>(numberOfBandsCache));
// fill the oldest with zeros
std::fill(currentCoefficient.begin(), currentCoefficient.end(), 0);
}
}
inline void gabor_process_entry(int band, int sampleIndex, std::complex<float>& coef, gaborator_transform_callback callback, uintptr_t callback_data) {
int coefficientIndex = sampleIndex / frequencyBinTimeStepSize;
int bandIndex = band - firstBandCache;
int circularIndex = coefficientIndex % int(coefficientSize);
auto& currentCoefficient = *coefficients[circularIndex];
// The first results have a negative audio sample index
// ignore these
if (coefficientIndex > 0 && bandIndex < numberOfBandsCache) {
// If a new index is reached, save the old (fixed) coefficients in the history
// Fill the array with zeros to get the max
if (coefficientIndex > mostRecentCoefficentIndex && coefficientIndex > coefficientSize) {
// keep the new maximum
mostRecentCoefficentIndex = coefficientIndex;
// "copy" the oldest data to the history
// the slice can be reused thanks to the oldest being filled with zeros just after
callback(callback_data, currentCoefficient.data(), static_cast<int>(numberOfBandsCache));
// fill the oldest with zeros
std::fill(currentCoefficient.begin(), currentCoefficient.end(), 0);
}
// due to reduction in precision (from audio sample accuracy to steps) multiple
// magnitudes could be placed in the same stepIndex, bandIndex pair.
// We take the maximum magnitudes value.
currentCoefficient[bandIndex] = std::max(currentCoefficient[bandIndex], std::abs(coef));
}
}
private:
std::vector<std::unique_ptr<std::vector<float>>> coefficients;
int firstBandCache = -1;
int numberOfBandsCache = 0;
int mostRecentCoefficentIndex = 0;
int frequencyBinTimeStepSize;
const int blockSize;
const int frequencyBinTimeStepSize;
int64_t t_in;
int min_band;
int sample_rate;
const int sample_rate;
int64_t latency;
int64_t coefficientSize;

View file

@ -12,20 +12,25 @@ int main() {
return 1;
}
auto ptr = gaborator_initialize(8192, 16000, 85, 110, 440, 7040, 128);
auto ptr = gaborator_initialize(1024 * 64, 16000, 85, 110, 440, 7040, 128);
float audioData[BLOCK_SIZE];
while (true){
auto read = fread(&audioData[0], sizeof(audioData[0]), sizeof(audioData) / sizeof(audioData[0]), fp);
if (read < sizeof(audioData) / sizeof(audioData[0])) { //EOF
break;
}
gaborator_transform(ptr, &audioData[0], sizeof(audioData) / sizeof(audioData[0]), [](uintptr_t, float*, int){
}, 0);
if (read < sizeof(audioData) / sizeof(audioData[0])) { //EOF
break;
}
}
gaborator_transform(ptr, nullptr, 0, [](uintptr_t, float*, int){
}, 0);
fclose(fp);
gaborator_release(ptr);