Mercurial > hg > audiostuff
diff spandsp-0.0.6pre17/tests/playout_tests.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 15:50:58 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.6pre17/tests/playout_tests.c Fri Jun 25 15:50:58 2010 +0200 @@ -0,0 +1,339 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * playout_tests.c + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2005 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: playout_tests.c,v 1.29 2009/05/30 15:23:14 steveu Exp $ + */ + +/*! \page playout_tests_page Playout (jitter buffering) tests +\section playout_tests_page_sec_1 What does it do? +These tests simulate timing jitter and packet loss in an audio stream, and see +how well the playout module copes. +*/ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sndfile.h> + +#include "spandsp.h" +#include "spandsp/private/time_scale.h" +#include "spandsp-sim.h" + +#define INPUT_FILE_NAME "playout_in.wav" +#define OUTPUT_FILE_NAME "playout_out.wav" + +#define BLOCK_LEN 160 + +static void dynamic_buffer_tests(void) +{ + playout_state_t *s; + playout_frame_t frame; + playout_frame_t *p; + plc_state_t plc; + time_scale_state_t ts; + int16_t *amp; + int16_t fill[BLOCK_LEN]; + int16_t buf[20*BLOCK_LEN]; + int16_t out[10*BLOCK_LEN]; + timestamp_t time_stamp; + timestamp_t next_actual_receive; + timestamp_t next_scheduled_receive; + int near_far_time_offset; + int rng; + int i; + int j; + int ret; + int len; + int inframes; + int outframes; + SNDFILE *inhandle; + SNDFILE *outhandle; + + if ((inhandle = sf_open_telephony_read(INPUT_FILE_NAME, 1)) == NULL) + { + fprintf(stderr, " Failed to open audio file '%s'\n", INPUT_FILE_NAME); + exit(2); + } + if ((outhandle = sf_open_telephony_write(OUTPUT_FILE_NAME, 1)) == NULL) + { + fprintf(stderr, " Failed to create audio file '%s'\n", OUTPUT_FILE_NAME); + exit(2); + } + + near_far_time_offset = 54321; + time_stamp = 12345; + next_actual_receive = time_stamp + near_far_time_offset; + next_scheduled_receive = 0; + for (i = 0; i < BLOCK_LEN; i++) + fill[i] = 32767; + + if ((s = playout_init(2*BLOCK_LEN, 15*BLOCK_LEN)) == NULL) + return; + plc_init(&plc); + time_scale_init(&ts, SAMPLE_RATE, 1.0); + for (i = 0; i < 1000000; i++) + { + if (i >= next_actual_receive) + { + amp = malloc(BLOCK_LEN*sizeof(int16_t)); + inframes = sf_readf_short(inhandle, amp, BLOCK_LEN); + if (inframes < BLOCK_LEN) + break; + ret = playout_put(s, + amp, + PLAYOUT_TYPE_SPEECH, + inframes, + time_stamp, + next_actual_receive); +#if 0 + switch (ret) + { + case PLAYOUT_OK: + printf("<< Record\n"); + break; + case PLAYOUT_ERROR: + printf("<< Error\n"); + break; + default: + printf("<< Eh?\n"); + break; + } +#endif + rng = rand() & 0xFF; + if (i < 100000) + rng = (rng*rng) >> 7; + else if (i < 200000) + rng = (rng*rng) >> 6; + else if (i < 300000) + rng = (rng*rng) >> 5; + else if (i < 400000) + rng = (rng*rng) >> 7; + time_stamp += BLOCK_LEN; + next_actual_receive = time_stamp + near_far_time_offset + rng; + } + if (i >= next_scheduled_receive) + { + do + { + ret = playout_get(s, &frame, next_scheduled_receive); + if (ret == PLAYOUT_DROP) + printf(">> Drop %d\n", next_scheduled_receive); + } + while (ret == PLAYOUT_DROP); + switch (ret) + { + case PLAYOUT_OK: + printf(">> Play %d\n", next_scheduled_receive); + plc_rx(&plc, frame.data, frame.sender_len); + len = time_scale(&ts, out, ((int16_t *) frame.data), frame.sender_len); +printf("len = %d\n", len); + for (j = 0; j < len; j++) + { + buf[2*j] = out[j]; + buf[2*j + 1] = 10*playout_current_length(s); + } + outframes = sf_writef_short(outhandle, buf, len); + if (outframes != len) + { + fprintf(stderr, " Error writing out sound\n"); + exit(2); + } + free(frame.data); + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_FILLIN: + printf(">> Fill %d\n", next_scheduled_receive); + plc_fillin(&plc, fill, BLOCK_LEN); + time_scale_rate(&ts, 0.5); + len = time_scale(&ts, out, fill, BLOCK_LEN); + time_scale_rate(&ts, 1.0); +printf("len = %d\n", len); + for (j = 0; j < len; j++) + { + buf[2*j] = out[j]; + buf[2*j + 1] = 10*playout_current_length(s); + } + outframes = sf_writef_short(outhandle, buf, len); + if (outframes != len) + { + fprintf(stderr, " Error writing out sound\n"); + exit(2); + } + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_DROP: + printf(">> Drop %d\n", next_scheduled_receive); + break; + case PLAYOUT_NOFRAME: + printf(">> No frame %d %d %d %d\n", next_scheduled_receive, playout_next_due(s), s->last_speech_sender_stamp, s->last_speech_sender_len); + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_EMPTY: + printf(">> Empty %d\n", next_scheduled_receive); + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_ERROR: + printf(">> Error %d\n", next_scheduled_receive); + next_scheduled_receive += BLOCK_LEN; + break; + default: + printf(">> Eh? %d\n", next_scheduled_receive); + break; + } + } + } + if (sf_close(inhandle) != 0) + { + fprintf(stderr, " Cannot close audio file '%s'\n", INPUT_FILE_NAME); + exit(2); + } + if (sf_close(outhandle) != 0) + { + fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_FILE_NAME); + exit(2); + } + + printf("%10" PRId32 " %10" PRId32 " %10d\n", s->state_just_in_time, s->state_late, playout_current_length(s)); + + /* Clear everything from the queue */ + while ((p = playout_get_unconditional(s))) + /*free(p->data)*/; + /* Now free the context itself */ + playout_free(s); +} +/*- End of function --------------------------------------------------------*/ + +static void static_buffer_tests(void) +{ + playout_state_t *s; + playout_frame_t frame; + playout_frame_t *p; + int type; + uint8_t fr[BLOCK_LEN]; + timestamp_t next_scheduled_send; + int transit_time; + timestamp_t next_actual_receive; + timestamp_t next_scheduled_receive; + int len; + int i; + int ret; + + next_scheduled_send = 0; + transit_time = 320; + next_actual_receive = next_scheduled_send + transit_time; + next_scheduled_receive = 960; + + memset(fr, 0, sizeof(fr)); + type = PLAYOUT_TYPE_SPEECH; + len = BLOCK_LEN; + + if ((s = playout_init(2*BLOCK_LEN, 2*BLOCK_LEN)) == NULL) + return; + for (i = 0; i < 1000000; i++) + { + if (i >= next_actual_receive) + { + ret = playout_put(s, + fr, + type, + len, + next_scheduled_send, + next_actual_receive); + switch (ret) + { + case PLAYOUT_OK: + printf("<< Record\n"); + break; + case PLAYOUT_ERROR: + printf("<< Error\n"); + break; + default: + printf("<< Eh?\n"); + break; + } + next_scheduled_send += BLOCK_LEN; + ret = rand() & 0xFF; + ret = (ret*ret) >> 7; + transit_time = 320 + ret; + next_actual_receive = next_scheduled_send + transit_time; + } + if (i >= next_scheduled_receive) + { + do + { + ret = playout_get(s, &frame, next_scheduled_receive); + } + while (ret == PLAYOUT_DROP); + switch (ret) + { + case PLAYOUT_OK: + printf(">> Play\n"); + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_FILLIN: + printf(">> Fill\n"); + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_DROP: + printf(">> Drop\n"); + break; + case PLAYOUT_NOFRAME: + printf(">> No frame\n"); + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_EMPTY: + printf(">> Empty\n"); + next_scheduled_receive += BLOCK_LEN; + break; + case PLAYOUT_ERROR: + printf(">> Error\n"); + next_scheduled_receive += BLOCK_LEN; + break; + default: + printf(">> Eh?\n"); + break; + } + } + } + /* Clear everything from the queue */ + while ((p = playout_get_unconditional(s))) + /*free(p->data)*/; + /* Now free the context itself */ + playout_free(s); +} +/*- End of function --------------------------------------------------------*/ + +int main(int argc, char *argv[]) +{ + printf("Dynamic buffering tests\n"); + dynamic_buffer_tests(); + printf("Static buffering tests\n"); + static_buffer_tests(); +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/