#define COHPSK_FS 7500 /* note this is a wierd
value to get an integer
oversampling rate */
+#define COHPSK_CLIP 6.5 /* hard clipping for Nc*Nc=14 to reduce PAPR */
#include "comp.h"
#include "modem_stats.h"
struct COHPSK *cohpsk_create(void);
void cohpsk_destroy(struct COHPSK *coh);
void cohpsk_mod(struct COHPSK *cohpsk, COMP tx_fdm[], int tx_bits[], int nbits);
-void cohpsk_clip(COMP tx_fdm[]);
+void cohpsk_clip(COMP tx_fdm[], float clip_thresh, int n);
void cohpsk_demod(struct COHPSK *cohpsk, float rx_bits[], int *sync, COMP rx_fdm[], int *nin_frame);
void cohpsk_get_demod_stats(struct COHPSK *cohpsk, struct MODEM_STATS *stats);
void cohpsk_set_verbose(struct COHPSK *coh, int verbose);
/* Defines */
#define OFDM_AMP_SCALE (2E5*1.1491/1.06) /* use to scale to 16 bit short */
+#define OFDM_CLIP (32767*0.35) /* experimentally derived constant to reduce PAPR to about 8dB */
struct OFDM;
gain.imag = 0.0;
for(i=0; i<COHPSK_M; i++) {
- tx_fdm[i].real = 0.0;
- tx_fdm[i].imag = 0.0;
+ tx_fdm[i].real = 0.0;
+ tx_fdm[i].imag = 0.0;
}
for(c=0; c<Nc; c++)
/* shift memory, inserting zeros at end */
- for(i=0; i<COHPSK_NSYM-1; i++)
- for(c=0; c<Nc; c++)
- tx_filter_memory[c][i] = tx_filter_memory[c][i+1];
-
+ for(i=0; i<COHPSK_NSYM-1; i++) {
for(c=0; c<Nc; c++) {
- tx_filter_memory[c][COHPSK_NSYM-1].real = 0.0;
- tx_filter_memory[c][COHPSK_NSYM-1].imag = 0.0;
+ tx_filter_memory[c][i] = tx_filter_memory[c][i+1];
+ }
+ }
+
+ for(c=0; c<Nc; c++) {
+ tx_filter_memory[c][COHPSK_NSYM-1].real = 0.0;
+ tx_filter_memory[c][COHPSK_NSYM-1].imag = 0.0;
}
+
}
void corr_with_pilots_comp(float *corr_out, float *mag_out, struct COHPSK *coh, int t, COMP dp_f_fine)
\*---------------------------------------------------------------------------*/
-void cohpsk_clip(COMP tx_fdm[])
+void cohpsk_clip(COMP tx_fdm[], float clip_thresh, int n)
{
COMP sam;
float mag;
int i;
- for(i=0; i<COHPSK_NOM_SAMPLES_PER_FRAME; i++) {
+ for(i=0; i<n; i++) {
sam = tx_fdm[i];
mag = cabsolute(sam);
- if (mag > COHPSK_CLIP) {
- sam = fcmult( COHPSK_CLIP/mag, sam);
+ if (mag > clip_thresh) {
+ sam = fcmult(clip_thresh/mag, sam);
}
tx_fdm[i] = sam;
}
#define COHPSK_NFILTER (COHPSK_NSYM*COHPSK_M)
#define COHPSK_EXCESS_BW 0.5 /* excess BW factor of root nyq filter */
#define COHPSK_NT 5 /* number of symbols we estimate timing over */
-#define COHPSK_CLIP 6.5 /* hard clipping for Nc*Nc=14 to reduce PAPR */
#include "fdmdv_internal.h"
#include "kiss_fft.h"
for(i=0; i<COHPSK_BITS_PER_FRAME*diversity; i++)
tx_bits[i] = tx_bits_char[i];
cohpsk_mod(cohpsk, tx_fdm, tx_bits, COHPSK_BITS_PER_FRAME*diversity);
- cohpsk_clip(tx_fdm);
+ cohpsk_clip(tx_fdm, COHPSK_CLIP, COHPSK_NOM_SAMPLES_PER_FRAME);
/* scale and save to disk as shorts */
/* cohpsk modulator */
cohpsk_mod(f->cohpsk, tx_fdm, f->codec_bits, COHPSK_BITS_PER_FRAME);
- if (f->clip)
- cohpsk_clip(tx_fdm);
+ if (f->clip)
+ cohpsk_clip(tx_fdm, COHPSK_CLIP, COHPSK_NOM_SAMPLES_PER_FRAME);
for(i=0; i<f->n_nat_modem_samples; i++)
mod_out[i] = fcmult(FDMDV_SCALE*NORM_PWR_COHPSK, tx_fdm[i]);
i = quisk_cfInterpDecim(mod_out, f->n_nat_modem_samples, f->ptFilter7500to8000, 16, 15);
mod_out[i] = fcmult(OFDM_AMP_SCALE*NORM_PWR_OFDM, asam);
}
- assert(f->clip == 0); /* todo: support clipping, requires some simulations and testing */
+ if (f->clip) {
+ //fprintf(stderr, "clip ");
+ cohpsk_clip(mod_out, OFDM_CLIP, f->interleave_frames*f->n_nat_modem_samples);
+ }
}
#endif
int mode;
int n_speech_samples;
int n_nom_modem_samples;
- int use_codectx, use_datatx, use_testframes, interleave_frames;
+ int use_codectx, use_datatx, use_testframes, interleave_frames, use_clip;
struct CODEC2 *c2;
int i;
if (argc < 4) {
printf("usage: %s 1600|700|700B|700C|700D|2400A|2400B|800XA InputRawSpeechFile OutputModemRawFile\n"
- " [--testframes] [--interleave depth] [--codectx] [--datatx]\n", argv[0]);
+ " [--testframes] [--interleave depth] [--codectx] [--datatx] [--clip 0|1]\n", argv[0]);
printf("e.g %s 1600 hts1a.raw hts1a_fdmdv.raw\n", argv[0]);
exit(1);
}
exit(1);
}
- use_codectx = 0; use_datatx = 0; use_testframes = 0; interleave_frames = 1;
+ use_codectx = 0; use_datatx = 0; use_testframes = 0; interleave_frames = 1; use_clip = 0;
if (argc > 4) {
for (i = 4; i < argc; i++) {
if (strcmp(argv[i], "--interleave") == 0) {
interleave_frames = atoi(argv[i+1]);
}
+ if (strcmp(argv[i], "--clip") == 0) {
+ use_clip = atoi(argv[i+1]);
+ }
}
}
freedv_set_snr_squelch_thresh(freedv, -100.0);
freedv_set_squelch_en(freedv, 1);
+ freedv_set_clip(freedv, use_clip);
n_speech_samples = freedv_get_n_speech_samples(freedv);
n_nom_modem_samples = freedv_get_n_nom_modem_samples(freedv);