⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test_repair.c

📁 linux系统下的音频通信
💻 C
字号:
#include "config_win32.h"#include "config_unix.h"#include "audio_types.h"#include "codec_types.h"#include "codec_state.h"#include "codec.h"#include "repair_types.h"#include "repair.h"#include "sndfile_types.h"#include "sndfile.h"#include "util.h"#include <stdlib.h>#include <stdio.h>/*  * test_repair: this test takes an audio file, codes it, and simulates * loss on the coded audio, and writes a file of what would be decoded * when error concealment is applied.   *//* drop code - want to have additive drop so if we run test with 5% * and 10% and the same seed, the loss pattern of the 10% is the 5% plus * another 5%. */#define DROP_ARRAY_SIZE 192000#define RANDOM_END 0x7fffffffstatic unsigned char drop_priv[DROP_ARRAY_SIZE];static int units_per_packet = 1;static void init_drop(int seed, double d){  int ndrop     = (int)(d * sizeof(drop_priv));  int dropped;  unsigned int rand_ceil = RANDOM_END - (RANDOM_END % DROP_ARRAY_SIZE);  unsigned int r;  memset(drop_priv, 0, sizeof(drop_priv));  srand48(seed);  for (dropped = 0; dropped < ndrop; dropped ++) {    /* Keep picking numbers until we get one in range and     * that has not already been picked.     */          while( (r = (mrand48() & 0x7fffffff)) > rand_ceil &&                  drop_priv[r % DROP_ARRAY_SIZE]);          drop_priv[r % DROP_ARRAY_SIZE] = 1;  }  printf("# dropping %d of %d frames\n", ndrop, DROP_ARRAY_SIZE);}static intdo_drop(){  static long int idx;  int d;    d   = drop_priv[idx / units_per_packet];  idx = (idx + 1) % DROP_ARRAY_SIZE;  return d;}#define READ_BUF_SIZE 2560static intread_and_encode(coded_unit        *out,                codec_state       *encoder,                 struct s_sndfile  *sf_in){        const codec_format_t *cf;        coded_unit           dummy;        sample               *buf;        uint16_t req_samples, act_samples;        req_samples = codec_get_samples_per_frame(encoder->id);        buf         = (sample*)block_alloc(sizeof(sample) * req_samples);        act_samples = (uint16_t)snd_read_audio(&sf_in, buf, req_samples);        if (req_samples != act_samples) {                memset(buf + act_samples, 0, sizeof(short) * (req_samples - act_samples));        }        cf = codec_get_format(encoder->id);        assert(cf != NULL);        dummy.id = codec_get_native_coding((uint16_t)cf->format.sample_rate,                                             (uint16_t)cf->format.channels);        dummy.state     = NULL;        dummy.state_len = 0;        dummy.data      = (u_char*)buf;        dummy.data_len  = req_samples * sizeof(short);        assert(out != NULL);        if (codec_encode(encoder, &dummy, out) == FALSE) {                abort();        }        block_free(dummy.data, dummy.data_len);        return (sf_in != NULL);}static voiddecode_and_write(struct s_sndfile           *sf_out,                 struct s_codec_state_store *decoder_states,                 media_data                 *md){        codec_state *decoder;        coded_unit  *cu;        int          i;        assert(md->nrep > 0);        for(i = 0; i < md->nrep; i++) {                if (codec_is_native_coding(md->rep[i]->id)) {                        break;                }        }                        if (i == md->nrep) {                /* no decoded audio available for frame */                cu = (coded_unit*)block_alloc(sizeof(coded_unit));                assert(cu != NULL);                memset(cu, 0, sizeof(coded_unit));                decoder = codec_state_store_get(decoder_states, md->rep[0]->id);                codec_decode(decoder, md->rep[0], cu);                assert(md->rep[md->nrep] == NULL);                md->rep[md->nrep] = cu;                md->nrep++;        }                assert(codec_is_native_coding(md->rep[md->nrep - 1]->id));        assert(sf_out != NULL);        snd_write_audio(&sf_out,                         (sample*)md->rep[md->nrep - 1]->data,                                md->rep[md->nrep - 1]->data_len / sizeof(sample));             }       static voidtest_repair(struct s_sndfile *sf_out,             codec_id_t        cid,            repair_id_t       repair_type,            struct s_sndfile *sf_in){        codec_state                *encoder;                struct s_codec_state_store *decoder_states;        media_data                 *md_prev, *md_cur;        coded_unit                 *cu;        int32_t                     consec_lost = 0, total_lost, total_done;        const codec_format_t       *cf;        uint16_t                    i;        repair_id_t                 repair_none;        for (i = 0; i < repair_get_count(); i++) {                const repair_details_t *rd;                rd = repair_get_details(i);                if (strcasecmp(rd->name, "none") == 0) {                        repair_none = rd->id;                        break;                }        }        codec_encoder_create(cid, &encoder);        codec_state_store_create(&decoder_states, DECODER);        cf = codec_get_format(cid);        /* Read and write one unit to kick off with */        media_data_create(&md_cur, 1);        read_and_encode(md_cur->rep[0], encoder, sf_in);        decode_and_write(sf_out, decoder_states, md_cur);        /* Initialize next reading cycle */        md_prev = md_cur;        md_cur  = NULL;        media_data_create(&md_cur, 1);        total_lost = total_done = 0;        while(read_and_encode(md_cur->rep[0], encoder, sf_in)) {                total_done++;                if (do_drop()) {                        total_lost++;                        media_data_destroy(&md_cur, sizeof(media_data));                        media_data_create(&md_cur, 0);                                                cu = (coded_unit*)block_alloc(sizeof(coded_unit));                        assert(cu != NULL);                        memset(cu, 0, sizeof(coded_unit));                        /* Loss happens - invoke repair */                        if (repair_type != repair_none) {                                cu->id = cid;                                repair(repair_type,                                       consec_lost,                                       decoder_states,                                       md_prev,                                       cu);                        } else {                                                                /* Create a silent unit */                                cu->id = codec_get_native_coding((uint16_t)cf->format.sample_rate,                                                                 (uint16_t)cf->format.channels);                                cu->state     = NULL;                                cu->state_len = 0;                                cu->data      = (u_char*)block_alloc(cf->format.bytes_per_block);                                cu->data_len  = cf->format.bytes_per_block;                                memset(cu->data, 0, cu->data_len);                        }                                                /* Add repaired audio to frame */                        md_cur->rep[md_cur->nrep] = cu;                        md_cur->nrep++;                                                consec_lost++;                } else {                        consec_lost = 0;                }                                decode_and_write(sf_out, decoder_states, md_cur);                media_data_destroy(&md_prev, sizeof(media_data));                md_prev = md_cur;                md_cur  = NULL;                media_data_create(&md_cur, 1);        }        printf("# Dropped %d frames out of %d (%f loss %%)\n", total_lost, total_done, 100.0 * total_lost / (double)total_done);                media_data_destroy(&md_cur, sizeof(media_data));        media_data_destroy(&md_prev, sizeof(media_data));                codec_encoder_destroy(&encoder);        codec_state_store_destroy(&decoder_states);}static voidusage(void){        fprintf(stderr, "test_repair [options] -c <codec> -r <repair> -d <rate> <src_file> <dst_file>where options are:\t-codecs to list available codecs\t-repairs to list available repair schemes\t-n to disable codec specific repair (default csra permitted)\t-s <seed> to set seed of rng (default 0)\t-u <units> set audio frames per packet (default 1 == 20ms)\n");        exit(-1);} static voidlist_repairs(void){        /* Repair interface is not consistent with other interfaces.          * Does not have get_format get_details type fn, just get_name         * (grumble, grumble, time, grumble) */        const repair_details_t *rd;        uint16_t i, cnt;        cnt = repair_get_count();        for(i = 0; i < cnt; i++) {                rd = repair_get_details(i);                printf("%s\n", rd->name);        }        return;}static intfile_and_codec_compatible(const sndfile_fmt_t *sff, codec_id_t cid){        const codec_format_t *cf;        cf = codec_get_format(cid);                if (cf == NULL) {                return FALSE;        }        if (sff->sample_rate == (uint32_t)cf->format.sample_rate &&            sff->channels    == (uint32_t)cf->format.channels) {                return TRUE;        }         return FALSE;}static voidlist_codecs(void){        uint32_t i, cnt;        codec_id_t cid;        const codec_format_t *cf;        cnt = codec_get_number_of_codecs();        for(i = 0; i < cnt; i++) {                cid = codec_get_codec_number(i);                cf  = codec_get_format(cid);                printf("%s\n", cf->long_name);        }        return;}static voidresolve_repair(char *reqname, repair_id_t *rid, const char **actualname){        uint16_t i,n;        const repair_details_t *rd;        n = repair_get_count();        for (i = 0; i < n; i++) {                rd = repair_get_details(i);                if (strcasecmp(rd->name, reqname) == 0) {                        *rid = rd->id;                        *actualname = rd->name;                        return;                }        }        fprintf(stderr, "Repair type %s not recognized\n", reqname);        exit(-1);}int main(int argc, char *argv[]){        const char *codec_name, *repair_name;        codec_id_t cid;        repair_id_t rid;        struct s_sndfile *sf_in = NULL, *sf_out = NULL;        sndfile_fmt_t     sff;        double drop = 0.0;        int ac, did_query = FALSE;        int csra  = TRUE; /* codec specific repair allowed */        long seed = 100;        codec_init();        ac = 1;        while(ac < argc && argv[ac][0] == '-') {                if (strlen(argv[ac]) > 2) {                        /* should be -codecs or -repairs */                        switch(argv[ac][1]) {                        case 'c':                                list_codecs();                                break;                        case 'r':                                list_repairs();                                 break;                        default:                                usage();                        }                        did_query = TRUE;                } else {                        if (argc - ac < 1) {                                usage();                        }                         switch(argv[ac][1]) {                        case 's':                                seed = atoi(argv[++ac]);                                break;                        case 'd':                                drop = strtod(argv[++ac], NULL);                                break;                        case 'c':                                cid  = codec_get_by_name(argv[++ac]);                                codec_name = argv[ac];                                break;                        case 'n':                                csra = FALSE;                                break;                        case 'r':                                resolve_repair(argv[++ac], &rid, &repair_name);                                break;                        case 'u':                                units_per_packet = atoi(argv[++ac]);                                break;                        default:                                usage();                        }                }                ac++;        }                if (did_query == TRUE) {                /* Not sensible to be running query and executing test */                exit(-1);        }        if (argc - ac != 2) {                usage();        }        if (snd_read_open(&sf_in, argv[ac], NULL) == FALSE) {                fprintf(stderr, "Could not open %s\n", argv[ac]);                exit(-1);        }        ac++;        if (snd_get_format(sf_in, &sff) == FALSE) {                fprintf(stderr, "Failed to get format of %s\n", argv[ac]);                exit(-1);        }        if (snd_write_open(&sf_out, argv[ac], "au", &sff) == FALSE) {                fprintf(stderr, "Could not open %s\n", argv[ac]);                exit(-1);        }        if (file_and_codec_compatible(&sff, cid) == FALSE) {                fprintf(stderr, "Codec and file type are not compatible\n");                exit(-1);        }        printf("# Parameters#\tseed: %ld#\tdrop: %.2f#\tcodec:  %s#\tunits per packet: %d#\trepair: %s#\tcodec specific repair (when available): %d#\tsource file: %s#\tdestination file %s\n",seed, drop, codec_name, units_per_packet, repair_name, csra, argv[argc - 2], argv[argc - 1]);	repair_set_codec_specific_allowed(csra);	init_drop(seed, drop);        test_repair(sf_out, cid, rid, sf_in);        /* snd_read_close(&sf_in) not needed because files gets closed         * at eof automatically.          */        snd_write_close(&sf_out);        codec_exit();        xmemdmp();        return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -