kgoba / ft8_lib

FT8 library
MIT License
201 stars 67 forks source link

int snr = 0; // TODO: compute SNR #25

Open F4HTB opened 2 years ago

F4HTB commented 2 years ago

Hello dear!

Thanks for your application. I try to use it for specific beacon. I just whant to ask you if it's possible to complet the snr for each num_candidates?

Thanks ;)

F4HTB commented 1 year ago

Hello,

I have maybe a solution. I add this in decode.c:

void swap(int* xp, int* yp)
{
    int temp = *xp;
    *xp = *yp;
    *yp = temp;
}

// Function to perform Selection Sort
void selectionSort(int arr[], int n)
{
    int i, j, min_idx;

    // One by one move boundary of unsorted subarray
    for (i = 0; i < n-1; i++)
    {
        // Find the minimum element in unsorted array
        min_idx = i;
        for (j = i+1; j < n; j++)
          if (arr[j] < arr[min_idx])
            min_idx = j;

        // Swap the found minimum element with the first element
        swap(&arr[min_idx], &arr[i]);
    }
}

int get_snr(const waterfall_t* wf, candidate_t candidate)
{

    //array with wf.num_blocks (row of watterfall) x 8*wf.freq_osr (signals witdh)
    //Get this watterfall zoom on the candidate symbols
    //Sort max to min and calculate max/min = ft8snr and return with substract of -26db for get snr on 2500hz

    float freq_hz = (candidate.freq_offset + (float)candidate.freq_sub / 2) / 0.160f;

    float minC = 0, maxC = 0;

    int i = 0;
    while(i<wf->num_blocks){

        int candidate_zoom[8*wf->freq_osr*wf->time_osr];

        for(int j = 0; j< 8; j++){

            for(int k = 0; k<wf->freq_osr*wf->time_osr; k++){

            candidate_zoom[(j*wf->freq_osr*wf->time_osr)+k] = wf->mag[( (i * wf->block_stride) + candidate.freq_offset + candidate.freq_sub + (j*wf->freq_osr*wf->time_osr) + k )];
            }

        }

        selectionSort(candidate_zoom,8*wf->freq_osr*wf->time_osr);

        for(int j = 0; j< wf->freq_osr*wf->time_osr*2; j++){
            minC += candidate_zoom[j+(2*wf->freq_osr*wf->time_osr)];

        }

        for(int j = 1; j<= wf->freq_osr*wf->time_osr; j++){
            maxC += candidate_zoom[(8*wf->freq_osr*wf->time_osr)-j];

        }

        i++;

    }

    minC = minC / (wf->num_blocks*wf->freq_osr*wf->time_osr*2);
    maxC = maxC / (wf->num_blocks*wf->freq_osr*wf->time_osr);

    int min = (int)(minC/2 - 240);
    int max = (int)(maxC/2 - 240);
    int snr= max - min - 26;

    return snr;

}

in ft8_find_sync i add:

...
    for(int i = 0; i<heap_size; i++){
        heap[i].snr = get_snr(wf,heap[i]);
    }

    return heap_size;
}

In decode.h

typedef struct
{
    int16_t score;       ///< Candidate score (non-negative number; higher score means higher likelihood)
    int16_t time_offset; ///< Index of the time block
    int16_t freq_offset; ///< Index of the frequency bin
    uint8_t time_sub;    ///< Index of the time subdivision used
    uint8_t freq_sub;    ///< Index of the frequency subdivision used
int16_t snr;         ///< SNR
} candidate_t;
kholia commented 1 year ago

@F4HTB Check out the https://github.com/kgoba/ft8_lib/tree/update_to_0_2 branch. It is able to generate SNR values similar to WSJT-X now.