2023-01-17 11:43:13 +01:00
|
|
|
#include "ziq2.h"
|
|
|
|
|
#ifdef BUILD_ZIQ2
|
|
|
|
|
#include "logger.h"
|
|
|
|
|
#include "dsp/buffer.h"
|
|
|
|
|
#include <volk/volk.h>
|
|
|
|
|
|
|
|
|
|
namespace ziq2
|
|
|
|
|
{
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#define __attribute__(x)
|
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
|
#endif
|
|
|
|
|
struct ziq2_info_pkt_hdr_t
|
|
|
|
|
{
|
|
|
|
|
uint64_t samplerate;
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#pragma pack(pop)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#define __attribute__(x)
|
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
|
#endif
|
|
|
|
|
struct ziq2_iq_pkt_hdr_t
|
|
|
|
|
{
|
|
|
|
|
uint8_t bit_depth;
|
|
|
|
|
float scale;
|
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
#pragma pack(pop)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
int ziq2_write_info_pkt(uint8_t *output, uint64_t samplerate, bool sync)
|
|
|
|
|
{
|
|
|
|
|
if (sync)
|
|
|
|
|
{
|
|
|
|
|
output[0] = 0x1a;
|
|
|
|
|
output[1] = 0xcf;
|
|
|
|
|
output[2] = 0xfc;
|
|
|
|
|
output[3] = 0x1d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ziq2_pkt_hdr_t *mdr = (ziq2_pkt_hdr_t *)&output[sync ? 4 : 0];
|
|
|
|
|
mdr->pkt_type = ZIQ2_PKT_INFO;
|
|
|
|
|
|
|
|
|
|
ziq2_info_pkt_hdr_t *hdr = (ziq2_info_pkt_hdr_t *)&output[(sync ? 4 : 0) + sizeof(ziq2_pkt_hdr_t)];
|
|
|
|
|
hdr->samplerate = samplerate;
|
|
|
|
|
|
|
|
|
|
mdr->pkt_size = sizeof(ziq2_info_pkt_hdr_t);
|
|
|
|
|
|
|
|
|
|
return (sync ? 4 : 0) + sizeof(ziq2_pkt_hdr_t) + mdr->pkt_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ziq2_write_iq_pkt(uint8_t *output, complex_t *input, float *mag_buf, int nsamples, int bit_depth, bool sync)
|
|
|
|
|
{
|
|
|
|
|
if (sync)
|
|
|
|
|
{
|
|
|
|
|
output[0] = 0x1a;
|
|
|
|
|
output[1] = 0xcf;
|
|
|
|
|
output[2] = 0xfc;
|
|
|
|
|
output[3] = 0x1d;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ziq2_pkt_hdr_t *mdr = (ziq2_pkt_hdr_t *)&output[sync ? 4 : 0];
|
|
|
|
|
mdr->pkt_type = ZIQ2_PKT_IQ;
|
|
|
|
|
|
|
|
|
|
ziq2_iq_pkt_hdr_t *hdr = (ziq2_iq_pkt_hdr_t *)&output[(sync ? 4 : 0) + sizeof(ziq2_pkt_hdr_t)];
|
|
|
|
|
|
|
|
|
|
uint32_t max_index = 0;
|
|
|
|
|
volk_32fc_magnitude_32f(mag_buf, (lv_32fc_t *)input, nsamples);
|
|
|
|
|
volk_32f_index_max_32u(&max_index, mag_buf, nsamples);
|
|
|
|
|
|
|
|
|
|
float scale = 0;
|
|
|
|
|
|
|
|
|
|
if (bit_depth == 8)
|
|
|
|
|
scale = 127.0f / mag_buf[max_index];
|
|
|
|
|
else if (bit_depth == 16)
|
2023-09-12 13:00:50 +02:00
|
|
|
scale = 32767.0f / mag_buf[max_index];
|
2023-01-17 11:43:13 +01:00
|
|
|
|
|
|
|
|
hdr->bit_depth = bit_depth;
|
|
|
|
|
hdr->scale = scale;
|
|
|
|
|
|
|
|
|
|
int final_size = (sync ? 4 : 0) + sizeof(ziq2_pkt_hdr_t) + sizeof(ziq2_iq_pkt_hdr_t);
|
|
|
|
|
|
|
|
|
|
if (bit_depth == 8)
|
|
|
|
|
{
|
|
|
|
|
volk_32f_s32f_convert_8i((int8_t *)&output[final_size], (float *)input, scale, nsamples * 2);
|
|
|
|
|
final_size = nsamples * sizeof(int8_t) * 2;
|
|
|
|
|
}
|
|
|
|
|
else if (bit_depth == 16)
|
|
|
|
|
{
|
|
|
|
|
volk_32f_s32f_convert_16i((int16_t *)&output[final_size], (float *)input, scale, nsamples * 2);
|
|
|
|
|
final_size = nsamples * sizeof(int16_t) * 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mdr->pkt_size = sizeof(ziq2_iq_pkt_hdr_t) + final_size;
|
|
|
|
|
|
|
|
|
|
return (sync ? 4 : 0) + sizeof(ziq2_pkt_hdr_t) + mdr->pkt_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ziq2_write_file_hdr(uint8_t *output, uint64_t samplerate, bool sync)
|
|
|
|
|
{
|
|
|
|
|
char *sig = (char *)&output[0];
|
|
|
|
|
sig[0] = 'Z';
|
|
|
|
|
sig[1] = 'I';
|
|
|
|
|
sig[2] = 'Q';
|
|
|
|
|
sig[3] = '2';
|
|
|
|
|
|
|
|
|
|
return 4 + ziq2_write_info_pkt(&output[4], samplerate, sync);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ziq2_read_info_pkt(uint8_t *input, uint64_t *samplerate)
|
|
|
|
|
{
|
2025-03-11 22:02:18 +01:00
|
|
|
// ziq2_pkt_hdr_t *mdr = (ziq2_pkt_hdr_t *)&input[0];
|
2023-01-17 11:43:13 +01:00
|
|
|
ziq2_info_pkt_hdr_t *hdr = (ziq2_info_pkt_hdr_t *)&input[sizeof(ziq2_pkt_hdr_t)];
|
|
|
|
|
*samplerate = hdr->samplerate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ziq2_read_iq_pkt(uint8_t *input, complex_t *output, int *nsamples)
|
|
|
|
|
{
|
|
|
|
|
ziq2_pkt_hdr_t *mdr = (ziq2_pkt_hdr_t *)&input[0];
|
|
|
|
|
ziq2_iq_pkt_hdr_t *hdr = (ziq2_iq_pkt_hdr_t *)&input[sizeof(ziq2_pkt_hdr_t)];
|
|
|
|
|
*nsamples = ((mdr->pkt_size - sizeof(ziq2_iq_pkt_hdr_t)) * 8) / (hdr->bit_depth * 2);
|
|
|
|
|
|
|
|
|
|
int final_size = sizeof(ziq2_pkt_hdr_t) + sizeof(ziq2_iq_pkt_hdr_t);
|
|
|
|
|
|
|
|
|
|
if (hdr->bit_depth == 8)
|
|
|
|
|
volk_8i_s32f_convert_32f((float *)output, (int8_t *)&input[final_size], hdr->scale, *nsamples * 2);
|
|
|
|
|
else if (hdr->bit_depth == 16)
|
|
|
|
|
volk_16i_s32f_convert_32f((float *)output, (int16_t *)&input[final_size], hdr->scale, *nsamples * 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ziq2_is_valid_ziq2(std::string file)
|
|
|
|
|
{
|
|
|
|
|
std::ifstream stream(file, std::ios::binary);
|
|
|
|
|
char signature[4];
|
|
|
|
|
stream.read((char *)signature, 4);
|
|
|
|
|
stream.close();
|
|
|
|
|
|
|
|
|
|
return std::string(&signature[0], &signature[4]) == ZIQ2_SIGNATURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t ziq2_try_parse_header(std::string file)
|
|
|
|
|
{
|
|
|
|
|
std::ifstream stream(file, std::ios::binary);
|
|
|
|
|
stream.seekg(8);
|
|
|
|
|
|
|
|
|
|
ziq2_pkt_hdr_t mdr;
|
|
|
|
|
stream.read((char *)&mdr, sizeof(ziq2_pkt_hdr_t));
|
|
|
|
|
|
|
|
|
|
if (mdr.pkt_type == ZIQ2_PKT_INFO)
|
|
|
|
|
{
|
|
|
|
|
ziq2_info_pkt_hdr_t hdr;
|
|
|
|
|
stream.read((char *)&hdr, sizeof(ziq2_info_pkt_hdr_t));
|
|
|
|
|
return hdr.samplerate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
#endif
|