block size independent output
This commit is contained in:
parent
636476a226
commit
d524cd1909
154
cgaborator.cpp
154
cgaborator.cpp
|
@ -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;
|
||||
|
||||
|
|
13
test.cpp
13
test.cpp
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue