You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OpenAudio_ArduinoLibrary/radioFT8Modulator_F32.cpp

134 lines
5.7 KiB

/*
* radioFT8modulator_F32
*
* Created: Bob Larkin 17 July 2022
*
* License: MIT License. Use at your own risk. See radioFT8Modulator.h file.
*
*/
#include "radioFT8Modulator_F32.h"
// 513 values of the sine wave in a float array:
#include "sinTable512_f32.h"
void RadioFT8Modulator_F32::update(void) {
audio_block_f32_t *blockOut;
uint16_t index;
float32_t a, b;
float32_t mag = 1.0f;
// uint32_t tu = micros();
if(ft8Transmit==false)
return;
// Sending tones. Sort out actions
blockOut = AudioStream_F32::allocate_f32(); // Get the output block
if (!blockOut)
return;
/* NOTE - ALL FT8 values shown in comments below are for a 48 kHz sample rate
* tone81SendCount 0 to 80 (81 tones)
* audioSampleCount 0 to 7679 for 48kHz sample rate
* sampleSent 0 to 622079 for 48kHz, 12.96 seconds, 81 tones
*/
// Send 128 audio samples of FSK sine waves
for(int kk=0; kk<128; kk++)
{
audioSampleCount = sampleSent % toneLength; // audioSampleCount is always derived from sampleSent
mag = magnitude; // Use down below
dphi = phaseIncrement;
if(tone81SendCount>0 && tone81SendCount<80) // Exclude end tones as special cases
{
if(audioSampleCount<pulseSegActive) // First part of tone with pulse shaping
{
// Overlap from previous tone with pulse falling 0.499608070 to 0.0 audioSampleCount 0 to 2815
dphi += (pulse[pulseSegActive - audioSampleCount - 1])*tones[tone81SendCount-1]*dphi_peak;
// plus current tone with pulse rising 0.500391960 to 1.0, audioSampleCount 0 to 2815
dphi += (1.0f - pulse[pulseSegActive - audioSampleCount - 1])*tones[tone81SendCount]*dphi_peak;
}
else if(audioSampleCount>=pulseSegActive && audioSampleCount<(toneLength - pulseSegActive)) // Center region, no pulses involved
{
// Center of tone with pulse level at 1.0, main tone, 2816 to 4863
dphi += tones[tone81SendCount]*dphi_peak;
}
else //if((audioSampleCount - 1)>(toneLength - pulseSegActive)) // Last part of tone with pulse shaping
{
// Current tone with pulse falling 1.0 to 0.500391960, audioSampleCount 4864 to 7679
dphi += (1.0f - pulse[audioSampleCount - (toneLength - pulseSegActive)])*tones[tone81SendCount]*dphi_peak;
// plus overlap from next tone with pulse rising 0.0 to 0.499608070, audioSampleCount 4864 to 7679
dphi += (pulse[audioSampleCount - (toneLength - pulseSegActive)])*tones[tone81SendCount + 1]*dphi_peak;
}
} // End of middle 79 tones
else if(tone81SendCount==0) // Key click pulse with no tone ahead
{
if((audioSampleCount)<(toneLength - pulseSegActive)) // audioSampleCount 0 to 4863 incl or 4864 points
{
// Pulse level at 1.0, main tone
dphi += tones[0]*dphi_peak;
}
else // Last part of tone with pulse shaping
{
// Current tone with pulse falling 1.0 to 0.50039196, audioSampleCount 4864 to 7679 or 2816 pts
dphi += (1.0f - pulse[audioSampleCount -(toneLength - pulseSegActive)])*tones[0]*dphi_peak;
// plus overlap from next tone with pulse rising 0.00000003 to 0.49960807 on 4864 to 7679
dphi += (pulse[audioSampleCount - (toneLength - pulseSegActive)])*tones[1]*dphi_peak;
}
if(audioSampleCount<cosineRampActive)
mag = magnitude*ramp[audioSampleCount];
else
mag = magnitude;
} // End of first tone
else if(tone81SendCount==80) // Key click pulse with no tone after
{
if(audioSampleCount<pulseSegActive) // First part of tone with pulse shaping
{
// Overlap from previous tone with pulse falling 0.499608070 to 0,00000
// over audioSampleCount 0 to 2815
dphi += (pulse[pulseSegActive - audioSampleCount - 1])*tones[79]*dphi_peak;
// plus current tone with pulse rising 0.50039196 to 1.0000000 0 to 2815
dphi += (1.0f - pulse[pulseSegActive - audioSampleCount - 1])*tones[80]*dphi_peak;
}
else //(audioSampleCount>=pulseSegActive) // Rest of region, no pulses involved
{
// Rest of tone with pulse level at 1.0, main tone, audioSampleCount 2816 to 7679
dphi += tones[80]*dphi_peak;
}
if(audioSampleCount>(toneLength - cosineRampActive))
{
mag = magnitude*ramp[toneLength - audioSampleCount];
}
else
mag = magnitude;
} // End of last tone
currentPhase += dphi;
while(currentPhase > 512.0f)
currentPhase -= 512.0f;
while(currentPhase < 0.0f)
currentPhase += 512.0f;
index = (uint16_t) currentPhase;
float32_t deltaPhase = currentPhase - (float32_t)index;
// Read two nearest values of input value from the sin table
a = sinTable512_f32[index];
b = sinTable512_f32[index+1];
blockOut->data[kk] = mag*(a+(b-a)*deltaPhase); // Linear interpolation
sampleSent++;
audioSampleCount = sampleSent % toneLength;
if(audioSampleCount == 0) // End of a tone send
{
if(++tone81SendCount == 81) // End of the 12.96 second period
{
tone81SendCount = 0;
ft8Transmit = false;
// Serial.println("End Transmission");
}
}
} // End, over all 128 audio output points
AudioStream_F32::transmit(blockOut);
AudioStream_F32::release (blockOut);
// Serial.println(micros() - tu);
}