int fsk_tx(fsk_tx_state_t *s, int16_t *amp, int len) { int sample; int bit; if (s->shutdown) return 0; /* Make the transitions between 0 and 1 phase coherent, but instantaneous jumps. There is currently no interpolation for bauds that end mid-sample. Mainstream users will not care. Some specialist users might have a problem with them, if they care about accurate transition timing. */ for (sample = 0; sample < len; sample++) { if ((s->baud_frac += s->baud_inc) >= 0x10000) { s->baud_frac -= 0x10000; if ((bit = s->get_bit(s->user_data)) == PUTBIT_END_OF_DATA) { s->shutdown = TRUE; break; } s->current_phase_rate = s->phase_rates[bit & 1]; } amp[sample] = dds_mod(&(s->phase_acc), s->current_phase_rate, s->scaling, 0); } return sample; }
SPAN_DECLARE(int) ademco_contactid_receiver_tx(ademco_contactid_receiver_state_t *s, int16_t amp[], int max_samples) { int i; int samples; switch (s->step) { case 0: samples = (s->remaining_samples > max_samples) ? max_samples : s->remaining_samples; vec_zeroi16(amp, samples); s->remaining_samples -= samples; if (s->remaining_samples > 0) return samples; span_log(&s->logging, SPAN_LOG_FLOW, "Initial silence finished\n"); s->step++; s->tone_phase_rate = dds_phase_rate(1400.0); s->tone_level = dds_scaling_dbm0(-11); s->tone_phase = 0; s->remaining_samples = ms_to_samples(100); return samples; case 1: samples = (s->remaining_samples > max_samples) ? max_samples : s->remaining_samples; for (i = 0; i < samples; i++) amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->tone_level, 0); s->remaining_samples -= samples; if (s->remaining_samples > 0) return samples; span_log(&s->logging, SPAN_LOG_FLOW, "1400Hz tone finished\n"); s->step++; s->remaining_samples = ms_to_samples(100); return samples; case 2: samples = (s->remaining_samples > max_samples) ? max_samples : s->remaining_samples; vec_zeroi16(amp, samples); s->remaining_samples -= samples; if (s->remaining_samples > 0) return samples; span_log(&s->logging, SPAN_LOG_FLOW, "Second silence finished\n"); s->step++; s->tone_phase_rate = dds_phase_rate(2300.0); s->tone_level = dds_scaling_dbm0(-11); s->tone_phase = 0; s->remaining_samples = ms_to_samples(100); return samples; case 3: samples = (s->remaining_samples > max_samples) ? max_samples : s->remaining_samples; for (i = 0; i < samples; i++) amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->tone_level, 0); s->remaining_samples -= samples; if (s->remaining_samples > 0) return samples; span_log(&s->logging, SPAN_LOG_FLOW, "2300Hz tone finished\n"); s->step++; s->remaining_samples = ms_to_samples(100); return samples; case 4: /* Idle here, waiting for a response */ return 0; case 5: samples = (s->remaining_samples > max_samples) ? max_samples : s->remaining_samples; vec_zeroi16(amp, samples); s->remaining_samples -= samples; if (s->remaining_samples > 0) return samples; span_log(&s->logging, SPAN_LOG_FLOW, "Sending kissoff\n"); s->step++; s->tone_phase_rate = dds_phase_rate(1400.0); s->tone_level = dds_scaling_dbm0(-11); s->tone_phase = 0; s->remaining_samples = ms_to_samples(850); return samples; case 6: samples = (s->remaining_samples > max_samples) ? max_samples : s->remaining_samples; for (i = 0; i < samples; i++) amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->tone_level, 0); s->remaining_samples -= samples; if (s->remaining_samples > 0) return samples; span_log(&s->logging, SPAN_LOG_FLOW, "1400Hz tone finished\n"); s->step = 4; s->remaining_samples = ms_to_samples(100); return samples; } return max_samples; }
SPAN_DECLARE(int) sig_tone_tx(sig_tone_tx_state_t *s, int16_t amp[], int len) { int i; int j; int k; int n; int16_t tone; int need_update; int high_low; for (i = 0; i < len; i += n) { if (s->current_tx_timeout) { if (s->current_tx_timeout <= len - i) { n = s->current_tx_timeout; need_update = TRUE; } else { n = len - i; need_update = FALSE; } s->current_tx_timeout -= n; } else { n = len - i; need_update = FALSE; } if (!(s->current_tx_tone & SIG_TONE_TX_PASSTHROUGH)) vec_zeroi16(&[i], n); /*endif*/ if ((s->current_tx_tone & (SIG_TONE_1_PRESENT | SIG_TONE_2_PRESENT))) { /* Are we in the early phase (high tone energy level), or the sustaining phase (low tone energy level) of tone generation? */ /* This doesn't try to get the high/low timing precise, as there is no value in doing so. It works block by block, and the blocks are normally quite short. */ if (s->high_low_timer > 0) { if (n > s->high_low_timer) n = s->high_low_timer; s->high_low_timer -= n; high_low = 0; } else { high_low = 1; } /*endif*/ for (k = 0; k < s->desc->tones; k++) { if ((s->current_tx_tone & tone_present_bits[k]) && s->phase_rate[k]) { for (j = i; j < i + n; j++) { tone = dds_mod(&s->phase_acc[k], s->phase_rate[k], s->tone_scaling[k][high_low], 0); amp[j] = saturated_add16(amp[j], tone); } /*endfor*/ } /*endif*/ } } /*endif*/ if (need_update && s->sig_update) s->sig_update(s->user_data, SIG_TONE_TX_UPDATE_REQUEST, 0, 0); /*endif*/ } /*endfor*/ return len; }
SPAN_DECLARE_NONSTD(int) tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples) { int samples; int limit; #if defined(SPANDSP_USE_FIXED_POINT) int16_t xamp; #else float xamp; #endif int i; if (s->current_section < 0) return 0; for (samples = 0; samples < max_samples; ) { limit = samples + s->duration[s->current_section] - s->current_position; if (limit > max_samples) limit = max_samples; s->current_position += (limit - samples); if (s->current_section & 1) { /* A silent section */ for ( ; samples < limit; samples++) amp[samples] = 0; } else { if (s->tone[0].phase_rate < 0) { /* Modulated tone */ for ( ; samples < limit; samples++) { /* There must be two, and only two, tones */ #if defined(SPANDSP_USE_FIXED_POINT) xamp = ((int32_t) dds_mod(&s->phase[0], -s->tone[0].phase_rate, s->tone[0].gain, 0) *(32767 + (int32_t) dds_mod(&s->phase[1], s->tone[1].phase_rate, s->tone[1].gain, 0))) >> 15; amp[samples] = xamp; #else xamp = dds_modf(&s->phase[0], -s->tone[0].phase_rate, s->tone[0].gain, 0) *(1.0f + dds_modf(&s->phase[1], s->tone[1].phase_rate, s->tone[1].gain, 0)); amp[samples] = (int16_t) lfastrintf(xamp); #endif } } else { for ( ; samples < limit; samples++) { #if defined(SPANDSP_USE_FIXED_POINT) xamp = 0; #else xamp = 0.0f; #endif for (i = 0; i < 4; i++) { if (s->tone[i].phase_rate == 0) break; #if defined(SPANDSP_USE_FIXED_POINT) xamp += dds_mod(&s->phase[i], s->tone[i].phase_rate, s->tone[i].gain, 0); #else xamp += dds_modf(&s->phase[i], s->tone[i].phase_rate, s->tone[i].gain, 0); #endif } /* Saturation of the answer is the right thing at this point. However, we are normally generating well controlled tones, that cannot clip. So, the overhead of doing saturation is a waste of valuable time. */ #if defined(SPANDSP_USE_FIXED_POINT) amp[samples] = xamp; #else amp[samples] = (int16_t) lfastrintf(xamp); #endif } } } if (s->current_position >= s->duration[s->current_section]) { s->current_position = 0; if (++s->current_section > 3 || s->duration[s->current_section] == 0) { if (!s->repeat) { /* Force a quick exit */ s->current_section = -1; break; } s->current_section = 0; } } }
static int power_surge_detector_tests(void) { SNDFILE *outhandle; power_surge_detector_state_t *sig; int i; int sample; int16_t amp[8000]; int16_t amp_out[2*8000]; awgn_state_t *awgnx; int32_t phase_rate; uint32_t phase_acc; int16_t phase_scale; float signal_power; int32_t signal_level; int signal_present; int prev_signal_present; int ok; int extremes[4]; if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); exit(2); } sig = power_surge_detector_init(NULL, -50.0f, 5.0f); prev_signal_present = false; phase_rate = dds_phase_rate(450.0f); phase_acc = 0; phase_scale = dds_scaling_dbm0(-33.0f); awgnx = awgn_init_dbm0(NULL, 1234567, -45.0f); extremes[0] = 8001; extremes[1] = -1; extremes[2] = 8001; extremes[3] = -1; for (sample = 0; sample < 800000; sample += 8000) { ok = 0; for (i = 0; i < 8000; i++) { amp[i] = awgn(awgnx); if (i < 4000) amp[i] += dds_mod(&phase_acc, phase_rate, phase_scale, 0); signal_level = power_surge_detector(sig, amp[i]); signal_present = (signal_level != 0); if (prev_signal_present != signal_present) { signal_power = power_surge_detector_current_dbm0(sig); if (signal_present) { if (ok == 0 && i >= 0 && i < 25) ok = 1; if (extremes[0] > i) extremes[0] = i; if (extremes[1] < i) extremes[1] = i; printf("On at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); } else { if (ok == 1 && i >= 4000 + 0 && i < 4000 + 35) ok = 2; if (extremes[2] > i) extremes[2] = i; if (extremes[3] < i) extremes[3] = i; printf("Off at %f (%fdBm0)\n", (sample + i)/8000.0, signal_power); } prev_signal_present = signal_present; } amp_out[2*i] = amp[i]; amp_out[2*i + 1] = signal_present*5000; } sf_writef_short(outhandle, amp_out, 8000); if (ok != 2 || extremes[0] < 1 || extremes[1] > 30 || extremes[2] < 4001 || extremes[3] > 4030) { printf(" Surge not detected correctly (%d)\n", ok); exit(2); } } if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); exit(2); } printf("Min on %d, max on %d, min off %d, max off %d\n", extremes[0], extremes[1], extremes[2], extremes[3]); power_surge_detector_free(sig); awgn_free(awgnx); return 0; }
SPAN_DECLARE(int) modem_connect_tones_tx(modem_connect_tones_tx_state_t *s, int16_t amp[], int len) { int16_t mod; int i; int xlen; i = 0; switch (s->tone_type) { case MODEM_CONNECT_TONES_FAX_CNG: for ( ; i < len; i++) { if (s->duration_timer > ms_to_samples(3000)) { if ((xlen = i + s->duration_timer - ms_to_samples(3000)) > len) xlen = len; s->duration_timer -= (xlen - i); for ( ; i < xlen; i++) amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->level, 0); } if (s->duration_timer > 0) { if ((xlen = i + s->duration_timer) > len) xlen = len; s->duration_timer -= (xlen - i); memset(amp + i, 0, sizeof(int16_t)*(xlen - i)); i = xlen; } if (s->duration_timer == 0) s->duration_timer = ms_to_samples(500 + 3000); } break; case MODEM_CONNECT_TONES_ANS: if (s->duration_timer < len) len = s->duration_timer; if (s->duration_timer > ms_to_samples(2600)) { /* There is some initial silence to be generated. */ if ((i = s->duration_timer - ms_to_samples(2600)) > len) i = len; memset(amp, 0, sizeof(int16_t)*i); } for ( ; i < len; i++) amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->level, 0); s->duration_timer -= len; break; case MODEM_CONNECT_TONES_ANS_PR: if (s->duration_timer < len) len = s->duration_timer; if (s->duration_timer > ms_to_samples(3300)) { if ((i = s->duration_timer - ms_to_samples(3300)) > len) i = len; memset(amp, 0, sizeof(int16_t)*i); } for ( ; i < len; i++) { if (--s->hop_timer <= 0) { s->hop_timer = ms_to_samples(450); s->tone_phase += 0x80000000; } amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, s->level, 0); } s->duration_timer -= len; break; case MODEM_CONNECT_TONES_ANSAM: if (s->duration_timer < len) len = s->duration_timer; if (s->duration_timer > ms_to_samples(3300)) { if ((i = s->duration_timer - ms_to_samples(3300)) > len) i = len; memset(amp, 0, sizeof(int16_t)*i); } for ( ; i < len; i++) { mod = (int16_t) (s->level + dds_mod(&s->mod_phase, s->mod_phase_rate, s->mod_level, 0)); amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, mod, 0); } s->duration_timer -= len; break; case MODEM_CONNECT_TONES_ANSAM_PR: if (s->duration_timer < len) len = s->duration_timer; if (s->duration_timer > ms_to_samples(3300)) { if ((i = s->duration_timer - ms_to_samples(3300)) > len) i = len; memset(amp, 0, sizeof(int16_t)*i); } for ( ; i < len; i++) { if (--s->hop_timer <= 0) { s->hop_timer = ms_to_samples(450); s->tone_phase += 0x80000000; } mod = (int16_t) (s->level + dds_mod(&s->mod_phase, s->mod_phase_rate, s->mod_level, 0)); amp[i] = dds_mod(&s->tone_phase, s->tone_phase_rate, mod, 0); } s->duration_timer -= len; break; } return len; }