#include "ziq2.h" #ifdef BUILD_ZIQ2 #include "logger.h" #include "dsp/buffer.h" #include 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) scale = 32767.0f / mag_buf[max_index]; 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) { ziq2_pkt_hdr_t *mdr = (ziq2_pkt_hdr_t *)&input[0]; 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