|
|
|
/*
|
|
|
|
* radioNoiseBlanker_F32.cpp
|
|
|
|
*
|
|
|
|
* 22 March 2020
|
|
|
|
* Bob Larkin, in support of the library:
|
|
|
|
* Chip Audette, OpenAudio, Apr 2017
|
|
|
|
* -------------------
|
|
|
|
*
|
|
|
|
* MIT License, Use at your own risk.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "radioNoiseBlanker_F32.h"
|
|
|
|
|
|
|
|
void radioNoiseBlanker_F32::update(void) {
|
|
|
|
audio_block_f32_t *blockIn0=NULL;
|
|
|
|
audio_block_f32_t *blockOut0=NULL;
|
|
|
|
audio_block_f32_t *blockIn1=NULL;
|
|
|
|
audio_block_f32_t *blockOut1=NULL;
|
|
|
|
uint16_t i;
|
|
|
|
float32_t absSignal;
|
|
|
|
|
|
|
|
// Get input block // <<Writable??
|
|
|
|
blockIn0 = AudioStream_F32::receiveWritable_f32(0);
|
|
|
|
if (!blockIn0) {
|
|
|
|
if(errorPrint) Serial.println("NB-ERR: No input memory");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(twoChannel) {
|
|
|
|
blockIn1 = AudioStream_F32::receiveWritable_f32(1);
|
|
|
|
if (!blockIn1) {
|
|
|
|
AudioStream_F32::release(blockIn0);
|
|
|
|
if(errorPrint) Serial.println("NB-ERR: No 1 input memory");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Are we not noise blanking?
|
|
|
|
if(! runNB) {
|
|
|
|
AudioStream_F32::transmit(blockIn0, 0); // send the unchanged data
|
|
|
|
AudioStream_F32::release (blockIn0);
|
|
|
|
if(twoChannel) {
|
|
|
|
AudioStream_F32::transmit(blockIn1, 1);
|
|
|
|
AudioStream_F32::release (blockIn1);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get a block for the output
|
|
|
|
blockOut0 = AudioStream_F32::allocate_f32();
|
|
|
|
if (!blockOut0) { // Didn't have any
|
|
|
|
if(errorPrint) Serial.println("NB-ERR: No output memory");
|
|
|
|
AudioStream_F32::release(blockIn0);
|
|
|
|
if(twoChannel)
|
|
|
|
AudioStream_F32::release(blockIn1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(twoChannel) {
|
|
|
|
blockOut1 = AudioStream_F32::allocate_f32();
|
|
|
|
if (!blockOut1) { // Didn't have any
|
|
|
|
if(errorPrint) Serial.println("NB-ERR: No output 1 memory");
|
|
|
|
AudioStream_F32::release(blockOut0);
|
|
|
|
AudioStream_F32::release(blockIn0);
|
|
|
|
AudioStream_F32::release(blockIn1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// delayData0[], and 1, always represents 256 points of I-F data. It is pre-gate and includes noise pulses.
|
|
|
|
// Go through new data, point i at a time, entering to delay line, looking
|
|
|
|
// for noise pulses. Then in same loop, move data to output buffer blockOut0->data
|
|
|
|
// based on whether gate is open or not.
|
|
|
|
for(i=0; i<block_size; i++) {
|
|
|
|
float32_t datai0 = blockIn0->data[i]; // ith data
|
|
|
|
delayData0[(i+in_index) & delayBufferMask] = datai0; // Put ith data to circular delay buffer
|
|
|
|
if(twoChannel) {
|
|
|
|
float32_t datai1 = blockIn1->data[i];
|
|
|
|
delayData1[(i+in_index) & delayBufferMask] = datai1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// All control comes from the 0 input (not the 1 input)
|
|
|
|
absSignal = fabsf(datai0); // Rectified I-F
|
|
|
|
runningSum += absSignal; // Update by adding one rectified point
|
|
|
|
runningSum -= delayData0[(i + in_index - RUNNING_SUM_SIZE) & delayBufferMask]; // & subtract one
|
|
|
|
|
|
|
|
pulseTime++; // This keeps track of leading and trailing delays of the gate pulse
|
|
|
|
if (absSignal > (threshold * runningSum)) { // A noise pulse event
|
|
|
|
if (gateOn == true) { // Signals are flowing, this is beginning of noise pulse event
|
|
|
|
gateOn = false;
|
|
|
|
pulseTime = -nAnticipation;
|
|
|
|
}
|
|
|
|
else { // gateOn==false, we are already in a noise pulse event
|
|
|
|
if (pulseTime > 0) { // Waiting for pulse event to end
|
|
|
|
pulseTime = 0; // Keep waiting
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { // Noise pulse is below threshold
|
|
|
|
if (gateOn == true) { // Signals are flowing normally
|
|
|
|
pulseTime = -9999;
|
|
|
|
}
|
|
|
|
else { // gateOn==false, we are already in a noise pulse event
|
|
|
|
if(pulseTime >= nDecay) { // End of a pulse event, turn gate on
|
|
|
|
gateOn = true;
|
|
|
|
pulseTime = -9999;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Ready to enter I-F data to output, offset in time by "nAnticipation"
|
|
|
|
if (pulseTime == -9999) {
|
|
|
|
blockOut0->data[i] = delayData0[(256 + i - nAnticipation) & delayBufferMask];
|
|
|
|
if(twoChannel)
|
|
|
|
blockOut1->data[i] = delayData1[(256 + i - nAnticipation) & delayBufferMask];
|
|
|
|
}
|
|
|
|
else { // -nAnticipation < pulseTime < nDecay i.e., blanked out
|
|
|
|
blockOut0->data[i] = 0.0f;
|
|
|
|
if(twoChannel)
|
|
|
|
blockOut1->data[i] = 0.0f;
|
|
|
|
}
|
|
|
|
} // End of loop point by point over input 128 data points
|
|
|
|
|
|
|
|
AudioStream_F32::release (blockIn0);
|
|
|
|
AudioStream_F32::transmit(blockOut0, 0); // send the delayed or blanked data
|
|
|
|
AudioStream_F32::release (blockOut0);
|
|
|
|
if(twoChannel) {
|
|
|
|
AudioStream_F32::release (blockIn1);
|
|
|
|
AudioStream_F32::transmit(blockOut1, 1); // send second "Q" channel
|
|
|
|
AudioStream_F32::release (blockOut1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update pointer in_index to delay line for next 128 update
|
|
|
|
in_index = (in_index + block_size) & delayBufferMask;
|
|
|
|
}
|
|
|
|
|