void rmlt_coefs_to_samples(int16_t coefs[], int16_t old_samples[], int16_t out_samples[], int dct_length, int16_t mag_shift) { int i; int half_dct_length; int last; int16_t new_samples[MAX_DCT_LENGTH]; const int16_t *win; int32_t sum; half_dct_length = dct_length >> 1; /* Perform a Type IV (inverse) DCT on the coefficients */ dct_type_iv_s(coefs, new_samples, dct_length); if (mag_shift > 0) { for (i = 0; i < dct_length; i++) new_samples[i] = shr(new_samples[i], mag_shift); } else if (mag_shift < 0) { mag_shift = negate(mag_shift); for (i = 0; i < dct_length; i++) new_samples[i] = shl(new_samples[i], mag_shift); } win = (dct_length == DCT_LENGTH) ? rmlt_to_samples_window : max_rmlt_to_samples_window; last = half_dct_length - 1; for (i = 0; i < half_dct_length; i++) { /* Get the first half of the windowed samples */ sum = L_mult(win[i], new_samples[last - i]); sum = L_mac(sum, win[dct_length - i - 1], old_samples[i]); out_samples[i] = xround(L_shl(sum, 2)); /* Get the second half of the windowed samples */ sum = L_mult(win[half_dct_length + i], new_samples[i]); sum = L_mac(sum, negate(win[last - i]), old_samples[last - i]); out_samples[half_dct_length + i] = xround(L_shl(sum, 2)); } /* Save the second half of the new samples for next time, when they will be the old samples. */ vec_copyi16(old_samples, &new_samples[half_dct_length], half_dct_length); }
int main(int argc, char *argv[]) { int16_t amp[2][BLOCK_LEN]; int16_t model_amp[2][BLOCK_LEN]; int16_t out_amp[2*BLOCK_LEN]; SNDFILE *inhandle; SNDFILE *outhandle; int outframes; int samples; int samples2; int i; int j; int test_bps; int line_model_no; int bits_per_test; int noise_level; int signal_level; int channel_codec; int rbs_pattern; int guard_tone_option; int opt; bool log_audio; channel_codec = MUNGE_CODEC_NONE; rbs_pattern = 0; test_bps = 2400; line_model_no = 0; decode_test_file = NULL; noise_level = -70; signal_level = -13; bits_per_test = 50000; guard_tone_option = V22BIS_GUARD_TONE_1800HZ; log_audio = false; while ((opt = getopt(argc, argv, "b:B:c:d:gG:lm:n:r:s:")) != -1) { switch (opt) { case 'b': test_bps = atoi(optarg); if (test_bps != 2400 && test_bps != 1200) { fprintf(stderr, "Invalid bit rate specified\n"); exit(2); } break; case 'B': bits_per_test = atoi(optarg); break; case 'c': channel_codec = atoi(optarg); break; case 'd': decode_test_file = optarg; break; case 'g': #if defined(ENABLE_GUI) use_gui = true; #else fprintf(stderr, "Graphical monitoring not available\n"); exit(2); #endif break; case 'G': guard_tone_option = atoi(optarg); break; case 'l': log_audio = true; break; case 'm': line_model_no = atoi(optarg); break; case 'n': noise_level = atoi(optarg); break; case 'r': rbs_pattern = atoi(optarg); break; case 's': signal_level = atoi(optarg); break; default: //usage(); exit(2); break; } } inhandle = NULL; if (decode_test_file) { /* We will decode the audio from a file. */ if ((inhandle = sf_open_telephony_read(decode_test_file, 1)) == NULL) { fprintf(stderr, " Cannot open audio file '%s'\n", decode_test_file); exit(2); } } outhandle = NULL; if (log_audio) { if ((outhandle = sf_open_telephony_write(OUT_FILE_NAME, 2)) == NULL) { fprintf(stderr, " Cannot create audio file '%s'\n", OUT_FILE_NAME); exit(2); } } memset(endpoint, 0, sizeof(endpoint)); for (i = 0; i < 2; i++) { endpoint[i].v22bis = v22bis_init(NULL, test_bps, guard_tone_option, (i == 0), v22bis_getbit, &endpoint[i], v22bis_putbit, &endpoint[i]); v22bis_tx_power(endpoint[i].v22bis, signal_level); /* Move the carrier off a bit */ endpoint[i].v22bis->tx.carrier_phase_rate = dds_phase_ratef((i == 0) ? 1207.0f : 2407.0f); v22bis_rx_set_qam_report_handler(endpoint[i].v22bis, qam_report, (void *) &endpoint[i]); span_log_set_level(&endpoint[i].v22bis->logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW); span_log_set_tag(&endpoint[i].v22bis->logging, (i == 0) ? "caller" : "answerer"); endpoint[i].smooth_power = 0.0f; endpoint[i].symbol_no = 0; bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]); } #if defined(ENABLE_GUI) if (use_gui) { endpoint[0].qam_monitor = qam_monitor_init(6.0f, V22BIS_CONSTELLATION_SCALING_FACTOR, "Calling modem"); endpoint[1].qam_monitor = qam_monitor_init(6.0f, V22BIS_CONSTELLATION_SCALING_FACTOR, "Answering modem"); } #endif if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, -15.0f, -15.0f, line_model_no, (float) noise_level, -15.0f, -15.0f, channel_codec, rbs_pattern)) == NULL) { fprintf(stderr, " Failed to create line model\n"); exit(2); } samples = 0; for (;;) { for (i = 0; i < 2; i++) { samples = v22bis_tx(endpoint[i].v22bis, amp[i], BLOCK_LEN); #if defined(ENABLE_GUI) if (use_gui) qam_monitor_update_audio_level(endpoint[i].qam_monitor, amp[i], samples); #endif if (samples == 0) { /* Note that we might get a few bad bits as the carrier shuts down. */ bert_result(&endpoint[i].bert_rx, &endpoint[i].latest_results); bert_init(&endpoint[i].bert_tx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_init(&endpoint[i].bert_rx, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20); bert_set_report(&endpoint[i].bert_rx, 10000, reporter, &endpoint[i]); printf("Restarting on zero output\n"); v22bis_restart(endpoint[i].v22bis, test_bps); } } #if 1 both_ways_line_model(model, model_amp[0], amp[0], model_amp[1], amp[1], samples); #else vec_copyi16(model_amp[0], amp[0], samples); vec_copyi16(model_amp[1], amp[1], samples); #endif if (decode_test_file) { samples2 = sf_readf_short(inhandle, model_amp[0], samples); if (samples2 != samples) break; } for (i = 0; i < 2; i++) { span_log_bump_samples(&endpoint[i].v22bis->logging, samples); v22bis_rx(endpoint[i ^ 1].v22bis, model_amp[i], samples); for (j = 0; j < samples; j++) out_amp[2*j + i] = model_amp[i][j]; for ( ; j < BLOCK_LEN; j++) out_amp[2*j + i] = 0; } if (log_audio) { outframes = sf_writef_short(outhandle, out_amp, BLOCK_LEN); if (outframes != BLOCK_LEN) { fprintf(stderr, " Error writing audio file\n"); exit(2); } } } #if defined(ENABLE_GUI) if (use_gui) qam_wait_to_end(endpoint[0].qam_monitor); #endif if (decode_test_file) { if (sf_close_telephony(inhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", decode_test_file); exit(2); } } if (log_audio) { if (sf_close_telephony(outhandle)) { fprintf(stderr, " Cannot close audio file '%s'\n", OUT_FILE_NAME); exit(2); } } return 0; }
int16_t samples_to_rmlt_coefs(const int16_t new_samples[], int16_t old_samples[], int16_t coefs[], int dct_length) { int i; int half_dct_length; int last; int16_t mag_shift; int16_t n; int16_t windowed_data[MAX_DCT_LENGTH]; const int16_t *win; int32_t acca; int32_t accb; int16_t temp; int16_t temp1; int16_t temp2; half_dct_length = dct_length >> 1; win = (dct_length == DCT_LENGTH) ? samples_to_rmlt_window : max_samples_to_rmlt_window; /* Get the first half of the windowed samples */ last = half_dct_length - 1; for (i = 0; i < half_dct_length; i++) { acca = L_mult(win[last - i], old_samples[last - i]); acca = L_mac(acca, win[half_dct_length + i], old_samples[half_dct_length + i]); windowed_data[i] = xround(acca); } /* Get the second half of the windowed samples */ last = dct_length - 1; for (i = 0; i < half_dct_length; i++) { acca = L_mult(win[last - i], new_samples[i]); acca = L_mac(acca, negate(win[i]), new_samples[last - i]); windowed_data[half_dct_length + i] = xround(acca); } /* Save the new samples for next time, when they will be the old samples. */ vec_copyi16(old_samples, new_samples, dct_length); /* Calculate how many bits to shift up the input to the DCT. */ temp1 = 0; for (i = 0; i < dct_length; i++) { temp2 = abs_s(windowed_data[i]); temp = sub(temp2, temp1); if (temp > 0) temp1 = temp2; } mag_shift = 0; temp = sub(temp1, 14000); if (temp < 0) { temp = sub(temp1, 438); temp = (temp < 0) ? add(temp1, 1) : temp1; accb = L_mult(temp, 9587); acca = L_shr(accb, 20); temp = norm_s((int16_t) acca); mag_shift = (temp == 0) ? 9 : sub(temp, 6); } acca = 0; for (i = 0; i < dct_length; i++) { temp = abs_s(windowed_data[i]); acca = L_add(acca, temp); } acca = L_shr(acca, 7); if (temp1 < acca) mag_shift = sub(mag_shift, 1); if (mag_shift > 0) { for (i = 0; i < dct_length; i++) windowed_data[i] = shl(windowed_data[i], mag_shift); } else if (mag_shift < 0) { n = negate(mag_shift); for (i = 0; i < dct_length; i++) windowed_data[i] = shr(windowed_data[i], n); } /* Perform a Type IV DCT on the windowed data to get the coefficients */ dct_type_iv_a(windowed_data, coefs, dct_length); return mag_shift; }