int main(int argc, char *argv[]) { AFfilehandle inhandle; AFfilehandle outhandle; AFfilesetup filesetup; plc_state_t plc; int inframes; int outframes; int16_t amp[1024]; int block_no; int lost_blocks; int block_len; int loss_rate; int dropit; int block_real; int block_synthetic; int tone; int i; uint32_t phase_acc; int32_t phase_rate; loss_rate = 25; block_len = 160; block_real = FALSE; block_synthetic = FALSE; tone = -1; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-l") == 0) { loss_rate = atoi(argv[++i]); continue; } if (strcmp(argv[i], "-b") == 0) { block_len = atoi(argv[++i]); continue; } if (strcmp(argv[i], "-t") == 0) { tone = atoi(argv[++i]); continue; } if (strcmp(argv[i], "-r") == 0) block_real = TRUE; if (strcmp(argv[i], "-s") == 0) block_synthetic = TRUE; } if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP) { fprintf(stderr, " Failed to create file setup\n"); exit(2); } afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE); afInitFileFormat(filesetup, AF_FILE_WAVE); afInitChannels(filesetup, AF_DEFAULT_TRACK, 1); phase_rate = 0; inhandle = NULL; if (tone < 0) { if ((inhandle = afOpenFile(INPUT_FILE_NAME, "r", NULL)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Failed to open wave file '%s'\n", INPUT_FILE_NAME); exit(2); } } else { phase_rate = dds_phase_ratef((float) tone); } if ((outhandle = afOpenFile(OUTPUT_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE) { fprintf(stderr, " Failed to open wave file '%s'\n", OUTPUT_FILE_NAME); exit(2); } plc_init(&plc); lost_blocks = 0; for (block_no = 0; ; block_no++) { if (tone < 0) { inframes = afReadFrames(inhandle, AF_DEFAULT_TRACK, amp, block_len); if (inframes != block_len) break; } else { if (block_no > 10000) break; for (i = 0; i < block_len; i++) amp[i] = (int16_t) dds_modf(&phase_acc, phase_rate, 10000.0, 0); inframes = block_len; } dropit = rand()/(RAND_MAX/100); if (dropit > loss_rate) { plc_rx(&plc, amp, inframes); if (block_real) memset(amp, 0, sizeof(int16_t)*inframes); } else { lost_blocks++; plc_fillin(&plc, amp, inframes); if (block_synthetic) memset(amp, 0, sizeof(int16_t)*inframes); } outframes = afWriteFrames(outhandle, AF_DEFAULT_TRACK, amp, inframes); if (outframes != inframes) { fprintf(stderr, " Error writing out sound\n"); exit(2); } } printf("Dropped %d of %d blocks\n", lost_blocks, block_no); if (tone < 0) { if (afCloseFile(inhandle) != 0) { fprintf(stderr, " Cannot close wave file '%s'\n", INPUT_FILE_NAME); exit(2); } } if (afCloseFile(outhandle) != 0) { fprintf(stderr, " Cannot close wave file '%s'\n", OUTPUT_FILE_NAME); exit(2); } afFreeFileSetup(filesetup); return 0; }
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; } } }
int tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples) { int samples; int limit; float xamp; float yamp; 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 { for ( ; samples < limit; samples++) { xamp = 0.0; if (s->phase_rate[0]) xamp = dds_modf(&(s->phase[0]), s->phase_rate[0], s->gain[0], 0); if (s->phase_rate[1]) { yamp = dds_modf(&(s->phase[1]), s->phase_rate[1], s->gain[1], 0); if (s->modulate) xamp *= (1.0f + yamp); else xamp += yamp; } /* 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. */ amp[samples] = (int16_t) rintf(xamp); } } 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; } } } return samples; }
int super_tone_tx(super_tone_tx_state_t *s, int16_t amp[], int max_samples) { int samples; int limit; int len; float xamp; super_tone_tx_step_t *tree; if (s->level < 0 || s->level > 3) return 0; samples = 0; tree = s->levels[s->level]; while (tree && samples < max_samples) { if (tree->tone) { /* A period of tone. A length of zero means infinite length. */ if (s->current_position == 0) { /* New step - prepare the tone generator */ s->phase_rate[0] = tree->phase_rate[0]; s->gain[0] = tree->gain[0]; s->phase_rate[1] = tree->phase_rate[1]; s->gain[1] = tree->gain[1]; } len = tree->length - s->current_position; if (tree->length == 0) { len = max_samples - samples; /* We just need to make current position non-zero */ s->current_position = 1; } else if (len > max_samples - samples) { len = max_samples - samples; s->current_position += len; } else { s->current_position = 0; } for (limit = len + samples; samples < limit; samples++) { xamp = 0.0; if (s->phase_rate[0]) xamp += dds_modf(&(s->phase[0]), s->phase_rate[0], s->gain[0], 0); if (s->phase_rate[1]) xamp += dds_modf(&(s->phase[1]), s->phase_rate[1], s->gain[1], 0); amp[samples] = (int16_t) rintf(xamp); } if (s->current_position) return samples; } else if (tree->length) { /* A period of silence. The length must always be explicitly stated. A length of zero does not give infinite silence. */ len = tree->length - s->current_position; if (len > max_samples - samples) { len = max_samples - samples; s->current_position += len; } else { s->current_position = 0; } memset(amp + samples, 0, sizeof(uint16_t)*len); samples += len; if (s->current_position) return samples; } /* Nesting has priority... */ if (tree->nest) { tree = tree->nest; s->levels[++s->level] = tree; s->cycles[s->level] = tree->cycles; } else { /* ...Next comes repeating, and finally moving forward a step. */ /* When repeating, note that zero cycles really means endless cycles. */ while (tree->cycles && --s->cycles[s->level] <= 0) { tree = tree->next; if (tree) { /* A fresh new step. */ s->levels[s->level] = tree; s->cycles[s->level] = tree->cycles; break; } /* If we are nested we need to pop, otherwise this is the end. */ if (s->level <= 0) { /* Mark the tone as completed */ s->levels[0] = NULL; break; } tree = s->levels[--s->level]; } } } return samples; }
int tone_gen(tone_gen_state_t *s, int16_t amp[], int max_samples) { int samples; int limit; float xamp; 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) { for ( ; samples < limit; samples++) { /* There must be two, and only two tones */ 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) lrintf(xamp); } } else { for ( ; samples < limit; samples++) { xamp = 0.0f; for (i = 0; i < 4; i++) { if (s->tone[i].phase_rate == 0) break; xamp += dds_modf(&s->phase[i], s->tone[i].phase_rate, s->tone[i].gain, 0); } /* 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. */ amp[samples] = (int16_t) lrintf(xamp); } } } 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; } } } return samples; }