static int decode_frame(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src, uint16_t src_len) { int ret, err; if (mbuf_get_left(src) < src_len) { DEBUG_WARNING("dec: corrupt frame %u < %u\n", mbuf_get_left(src), src_len); return EPROTO; } /* Make sure there is enough space in the buffer */ if (mbuf_get_space(dst) < st->fsize) { err = mbuf_resize(dst, dst->size + st->fsize); if (err) return err; } ret = celt_decode(st->dec, mbuf_buf(src), src_len, (short *)mbuf_buf(dst), st->frame_size); if (CELT_OK != ret) { DEBUG_WARNING("celt_decode: ret=%d\n", ret); } DEBUG_INFO("decode: %u -> %u\n", src_len, st->fsize); if (src) mbuf_advance(src, src_len); dst->end += st->fsize; return 0; }
int CeltCodec::Decode(const char *data, int dataLength, SoundBuffer &soundFrame) { soundFrame.data.resize(MUMBLE_AUDIO_SAMPLES_IN_FRAME * MUMBLE_AUDIO_SAMPLE_WIDTH / 8); soundFrame.frequency = MUMBLE_AUDIO_SAMPLE_RATE; soundFrame.is16Bit = true; soundFrame.stereo = false; return celt_decode(Decoder(), (const unsigned char*)data, dataLength, (celt_int16*)&soundFrame.data[0], MUMBLE_AUDIO_SAMPLES_IN_FRAME); }
static switch_status_t switch_celt_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag) { struct celt_context *context = codec->private_info; if (!context) { return SWITCH_STATUS_FALSE; } if (celt_decode(context->decoder_object, encoded_data, encoded_data_len, decoded_data, codec->implementation->samples_per_packet)) { return SWITCH_STATUS_GENERR; } *decoded_data_len = codec->implementation->decoded_bytes_per_packet; return SWITCH_STATUS_SUCCESS; }
SWIGEXPORT jint JNICALL Java_com_morlunk_jumble_audio_celt11_CELT11JNI_celt_1decode(JNIEnv *jenv, jclass jcls, jlong jarg1, jbyteArray jarg2, jint jarg3, jshortArray jarg4, jint jarg5) { jint jresult = 0 ; CELTDecoder *arg1 = (CELTDecoder *) 0 ; unsigned char *arg2 = (unsigned char *) 0 ; int arg3 ; celt_int16 *arg4 = (celt_int16 *) 0 ; int arg5 ; int result; (void)jenv; (void)jcls; arg1 = *(CELTDecoder **)&jarg1; { arg2 = (char *) (*jenv)->GetByteArrayElements(jenv, jarg2, 0); } arg3 = (int)jarg3; { if (!jarg4) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); return 0; } if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); return 0; } arg4 = (celt_int16 *) (*jenv)->GetShortArrayElements(jenv, jarg4, 0); } arg5 = (int)jarg5; result = (int)celt_decode(arg1,(unsigned char const *)arg2,arg3,arg4,arg5); jresult = (jint)result; { (*jenv)->ReleaseByteArrayElements(jenv, jarg2, (jbyte *) arg2, 0); } { (*jenv)->ReleaseShortArrayElements(jenv, jarg4, (jshort *)arg4, 0); } return jresult; }
static int celt_codec_decoder(const struct PluginCodec_Definition * codec, void * context, const void * fromPtr, unsigned * fromLen, void * toPtr, unsigned * toLen, unsigned int * flag) { CELTContext *celt = (CELTContext *)context; if (*toLen < codec->parm.audio.samplesPerFrame*sizeof(short)) return FALSE; if (*fromLen == 0) return FALSE; if (celt_decode(celt->decoder_state, (char *)fromPtr, *fromLen, (short *)toPtr) < 0) { return 0; } *toLen = codec->parm.audio.samplesPerFrame*sizeof(short); return TRUE; }
int main(int argc, char **argv) { int c; int option_index = 0; char *inFile, *outFile; FILE *fin, *fout=NULL; short out[MAX_FRAME_SIZE]; short output[MAX_FRAME_SIZE]; int frame_size=0, granule_frame_size=0; void *st=NULL; CELTMode *mode=NULL; int packet_count=0; int stream_init = 0; int quiet = 0; ogg_int64_t page_granule=0, last_granule=0; int skip_samples=0, page_nb_packets; struct option long_options[] = { {"help", no_argument, NULL, 0}, {"quiet", no_argument, NULL, 0}, {"version", no_argument, NULL, 0}, {"version-short", no_argument, NULL, 0}, {"rate", required_argument, NULL, 0}, {"mono", no_argument, NULL, 0}, {"stereo", no_argument, NULL, 0}, {"packet-loss", required_argument, NULL, 0}, {0, 0, 0, 0} }; ogg_sync_state oy; ogg_page og; ogg_packet op; ogg_stream_state os; int enh_enabled; int nframes=2; int print_bitrate=0; int close_in=0; int eos=0; int forceMode=-1; int audio_size=0; float loss_percent=-1; int channels=-1; int rate=0; int extra_headers=0; int wav_format=0; int lookahead=0; int celt_serialno = -1; int firstpacket = 1; enh_enabled = 1; /*Process options*/ while(1) { c = getopt_long (argc, argv, "hvV", long_options, &option_index); if (c==-1) break; switch(c) { case 0: if (strcmp(long_options[option_index].name,"help")==0) { usage(); exit(0); } else if (strcmp(long_options[option_index].name,"quiet")==0) { quiet = 1; } else if (strcmp(long_options[option_index].name,"version")==0) { version(); exit(0); } else if (strcmp(long_options[option_index].name,"version-short")==0) { version_short(); exit(0); } else if (strcmp(long_options[option_index].name,"mono")==0) { channels=1; } else if (strcmp(long_options[option_index].name,"stereo")==0) { channels=2; } else if (strcmp(long_options[option_index].name,"rate")==0) { rate=atoi (optarg); } else if (strcmp(long_options[option_index].name,"packet-loss")==0) { loss_percent = atof(optarg); } break; case 'h': usage(); exit(0); break; case 'v': version(); exit(0); break; case 'V': print_bitrate=1; break; case '?': usage(); exit(1); break; } } if (argc-optind!=2 && argc-optind!=1) { usage(); exit(1); } inFile=argv[optind]; if (argc-optind==2) outFile=argv[optind+1]; else outFile = ""; wav_format = strlen(outFile)>=4 && ( strcmp(outFile+strlen(outFile)-4,".wav")==0 || strcmp(outFile+strlen(outFile)-4,".WAV")==0); /*Open input file*/ if (strcmp(inFile, "-")==0) { #if defined WIN32 || defined _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif fin=stdin; } else { fin = fopen(inFile, "rb"); if (!fin) { perror(inFile); exit(1); } close_in=1; } /*Init Ogg data struct*/ ogg_sync_init(&oy); /*Main decoding loop*/ while (1) { char *data; int i, nb_read; /*Get the ogg buffer for writing*/ data = ogg_sync_buffer(&oy, 200); /*Read bitstream from input file*/ nb_read = fread(data, sizeof(char), 200, fin); ogg_sync_wrote(&oy, nb_read); /*Loop for all complete pages we got (most likely only one)*/ while (ogg_sync_pageout(&oy, &og)==1) { if (stream_init == 0) { ogg_stream_init(&os, ogg_page_serialno(&og)); stream_init = 1; } if (ogg_page_serialno(&og) != os.serialno) { /* so all streams are read. */ ogg_stream_reset_serialno(&os, ogg_page_serialno(&og)); } /*Add page to the bitstream*/ ogg_stream_pagein(&os, &og); page_granule = ogg_page_granulepos(&og); page_nb_packets = ogg_page_packets(&og); if (page_granule>0 && frame_size) { /* FIXME: shift the granule values if --force-* is specified */ skip_samples = frame_size*(page_nb_packets*granule_frame_size*nframes - (page_granule-last_granule))/granule_frame_size; if (ogg_page_eos(&og)) skip_samples = -skip_samples; /*else if (!ogg_page_bos(&og)) skip_samples = 0;*/ } else { skip_samples = 0; } /*printf ("page granulepos: %d %d %d\n", skip_samples, page_nb_packets, (int)page_granule);*/ last_granule = page_granule; /*Extract all available packets*/ while (!eos && ogg_stream_packetout(&os, &op) == 1 && op.bytes>=8) { if (!memcmp(op.packet, "CELT ", 8)) { celt_serialno = os.serialno; } if (celt_serialno == -1 || os.serialno != celt_serialno) break; /*If first packet, process as CELT header*/ if (packet_count==0) { st = process_header(&op, enh_enabled, &frame_size, &granule_frame_size, &rate, &nframes, forceMode, &channels, &lookahead, &extra_headers, quiet, &mode); if (!st) exit(1); if (!nframes) nframes=1; fout = out_file_open(outFile, rate, &channels); } else if (packet_count==1) { if (!quiet) print_comments((char*)op.packet, op.bytes); } else if (packet_count<=1+extra_headers) { /* Ignore extra headers */ } else { int lost=0; if (loss_percent>0 && 100*((float)rand())/RAND_MAX<loss_percent) lost=1; /*End of stream condition*/ if (op.e_o_s && os.serialno == celt_serialno) /* don't care for anything except celt eos */ eos=1; { int ret; /*Decode frame*/ if (!lost) ret = celt_decode(st, (unsigned char*)op.packet, op.bytes, output); else ret = celt_decode(st, NULL, 0, output); /*for (i=0;i<frame_size*channels;i++) printf ("%d\n", (int)output[i]);*/ if (ret!=0) { fprintf (stderr, "Decoding error: corrupted stream?\n"); break; } if (print_bitrate) { celt_int32 tmp=op.bytes; char ch=13; fputc (ch, stderr); fprintf (stderr, "Bitrate in use: %d bytes/packet ", tmp); } /*Convert to short and save to output file*/ if (strlen(outFile)!=0) { for (i=0;i<frame_size*channels;i++) out[i]=le_short(output[i]); } else { for (i=0;i<frame_size*channels;i++) out[i]=output[i]; } { int frame_offset = 0; int new_frame_size = frame_size; /*printf ("packet %d %d\n", packet_no, skip_samples);*/ /*fprintf (stderr, "packet %d %d %d\n", packet_no, skip_samples, lookahead);*/ if (firstpacket == 1) { /*printf ("chopping first packet\n");*/ new_frame_size -= lookahead; frame_offset = lookahead; firstpacket = 0; } if (new_frame_size>0) { #if defined WIN32 || defined _WIN32 if (strlen(outFile)==0) WIN_Play_Samples (out+frame_offset*channels, sizeof(short) * new_frame_size*channels); else #endif fwrite(out+frame_offset*channels, sizeof(short), new_frame_size*channels, fout); audio_size+=sizeof(short)*new_frame_size*channels; } } } } packet_count++; } } if (feof(fin)) break; } if (fout && wav_format) { if (fseek(fout,4,SEEK_SET)==0) { int tmp; tmp = le_int(audio_size+36); fwrite(&tmp,4,1,fout); if (fseek(fout,32,SEEK_CUR)==0) { tmp = le_int(audio_size); fwrite(&tmp,4,1,fout); } else { fprintf (stderr, "First seek worked, second didn't\n"); } } else { fprintf (stderr, "Cannot seek on wave file, size will be incorrect\n"); } } if (st) { celt_decoder_destroy(st); celt_mode_destroy(mode); } else { fprintf (stderr, "This doesn't look like a CELT file\n"); } if (stream_init) ogg_stream_clear(&os); ogg_sync_clear(&oy); #if defined WIN32 || defined _WIN32 if (strlen(outFile)==0) WIN_Audio_close (); #endif if (close_in) fclose(fin); if (fout != NULL) fclose(fout); return 0; }
static GstFlowReturn celt_dec_chain_parse_data (GstCeltDec * dec, GstBuffer * buf, GstClockTime timestamp, GstClockTime duration) { GstFlowReturn res = GST_FLOW_OK; gint size; guint8 *data; GstBuffer *outbuf; gint16 *out_data; gint error = CELT_OK; if (timestamp != -1) { dec->segment.last_stop = timestamp; dec->granulepos = -1; } if (buf) { data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); GST_DEBUG_OBJECT (dec, "received buffer of size %u", size); if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf) && GST_BUFFER_OFFSET_END_IS_VALID (buf)) { dec->granulepos = GST_BUFFER_OFFSET_END (buf); GST_DEBUG_OBJECT (dec, "Taking granulepos from upstream: %" G_GUINT64_FORMAT, dec->granulepos); } /* copy timestamp */ } else { /* concealment data, pass NULL as the bits parameters */ GST_DEBUG_OBJECT (dec, "creating concealment data"); data = NULL; size = 0; } res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header.nb_channels * 2, GST_PAD_CAPS (dec->srcpad), &outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } out_data = (gint16 *) GST_BUFFER_DATA (outbuf); GST_LOG_OBJECT (dec, "decoding frame"); error = celt_decode (dec->state, data, size, out_data); if (error != CELT_OK) { GST_WARNING_OBJECT (dec, "Decoding error: %d", error); return GST_FLOW_ERROR; } if (dec->granulepos == -1) { if (dec->segment.format != GST_FORMAT_TIME) { GST_WARNING_OBJECT (dec, "segment not initialized or not TIME format"); dec->granulepos = dec->frame_size; } else { dec->granulepos = gst_util_uint64_scale_int (dec->segment.last_stop, dec->header.sample_rate, GST_SECOND) + dec->frame_size; } GST_DEBUG_OBJECT (dec, "granulepos=%" G_GINT64_FORMAT, dec->granulepos); } GST_BUFFER_OFFSET (outbuf) = dec->granulepos - dec->frame_size; GST_BUFFER_OFFSET_END (outbuf) = dec->granulepos; GST_BUFFER_TIMESTAMP (outbuf) = gst_util_uint64_scale_int (dec->granulepos - dec->frame_size, GST_SECOND, dec->header.sample_rate); GST_BUFFER_DURATION (outbuf) = dec->frame_duration; dec->granulepos += dec->frame_size; dec->segment.last_stop += dec->frame_duration; GST_LOG_OBJECT (dec, "pushing buffer with ts=%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), GST_TIME_ARGS (dec->frame_duration)); res = gst_pad_push (dec->srcpad, outbuf); if (res != GST_FLOW_OK) GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); return res; }
int main(int argc, char *argv[]) { int err; char *inFile, *outFile; FILE *fin, *fout; CELTMode *mode=NULL; CELTEncoder *enc; CELTDecoder *dec; int len; celt_int32 frame_size, channels; int bytes_per_packet; unsigned char data[MAX_PACKET]; int rate; int complexity; #if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) int i; double rmsd = 0; #endif int count = 0; celt_int32 skip; celt_int16 *in, *out; if (argc != 9 && argc != 8 && argc != 7) { fprintf (stderr, "Usage: testcelt <rate> <channels> <frame size> " " <bytes per packet> [<complexity> [packet loss rate]] " "<input> <output>\n"); return 1; } rate = atoi(argv[1]); channels = atoi(argv[2]); frame_size = atoi(argv[3]); mode = celt_mode_create(rate, frame_size, NULL); if (mode == NULL) { fprintf(stderr, "failed to create a mode\n"); return 1; } bytes_per_packet = atoi(argv[4]); if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET) { fprintf (stderr, "bytes per packet must be between 0 and %d\n", MAX_PACKET); return 1; } inFile = argv[argc-2]; fin = fopen(inFile, "rb"); if (!fin) { fprintf (stderr, "Could not open input file %s\n", argv[argc-2]); return 1; } outFile = argv[argc-1]; fout = fopen(outFile, "wb+"); if (!fout) { fprintf (stderr, "Could not open output file %s\n", argv[argc-1]); return 1; } enc = celt_encoder_create_custom(mode, channels, &err); if (err != 0) { fprintf(stderr, "Failed to create the encoder: %s\n", celt_strerror(err)); return 1; } dec = celt_decoder_create_custom(mode, channels, &err); if (err != 0) { fprintf(stderr, "Failed to create the decoder: %s\n", celt_strerror(err)); return 1; } celt_decoder_ctl(dec, CELT_GET_LOOKAHEAD(&skip)); if (argc>7) { complexity=atoi(argv[5]); celt_encoder_ctl(enc,CELT_SET_COMPLEXITY(complexity)); } in = (celt_int16*)malloc(frame_size*channels*sizeof(celt_int16)); out = (celt_int16*)malloc(frame_size*channels*sizeof(celt_int16)); while (!feof(fin)) { int ret; err = fread(in, sizeof(short), frame_size*channels, fin); if (feof(fin)) break; len = celt_encode(enc, in, frame_size, data, bytes_per_packet); if (len <= 0) fprintf (stderr, "celt_encode() failed: %s\n", celt_strerror(len)); /* This is for simulating bit errors */ #if 0 int errors = 0; int eid = 0; /* This simulates random bit error */ for (i=0;i<len*8;i++) { if (rand()%atoi(argv[8])==0) { if (i<64) { errors++; eid = i; } data[i/8] ^= 1<<(7-(i%8)); } } if (errors == 1) data[eid/8] ^= 1<<(7-(eid%8)); else if (errors%2 == 1) data[rand()%8] ^= 1<<rand()%8; #endif #if 1 /* Set to zero to use the encoder's output instead */ /* This is to simulate packet loss */ if (argc==9 && rand()%1000<atoi(argv[argc-3])) /*if (errors && (errors%2==0))*/ ret = celt_decode(dec, NULL, len, out, frame_size); else ret = celt_decode(dec, data, len, out, frame_size); if (ret < 0) fprintf(stderr, "celt_decode() failed: %s\n", celt_strerror(ret)); #else for (i=0;i<ret*channels;i++) out[i] = in[i]; #endif #if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) for (i=0;i<ret*channels;i++) { rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]); /*out[i] -= in[i];*/ } #endif count++; fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout); skip = 0; } PRINT_MIPS(stderr); celt_encoder_destroy(enc); celt_decoder_destroy(dec); fclose(fin); fclose(fout); celt_mode_destroy(mode); free(in); free(out); #if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH) if (rmsd > 0) { rmsd = sqrt(rmsd/(1.0*frame_size*channels*count)); fprintf (stderr, "Error: encoder doesn't match decoder\n"); fprintf (stderr, "RMS mismatch is %f\n", rmsd); return 1; } else { fprintf (stderr, "Encoder matches decoder!!\n"); } #endif return 0; }
int main(int argc, char** argv) { int current, pos; celt_int16 * sample_buffer; unsigned char * encoded_buffer; double * out_buffer; int sample_rate; int sample_bits; int sample_channels; int sample_buffer_size; int sample; int sample_msec; int sample_size; float freq; double ampl, phase, frequency; int i, j, k; uint32_t frames; // FIXME! 4 byte! FILE * fd; int bad; int badbytes, lostbytes, totalbytes; struct Chord chord; // Sound output through libao struct AOutput * device; CELTMode * cm; CELTEncoder * ce; CELTDecoder * cd; int * error; int compressed; srand(time(NULL)); // Opening sound file for reading source data fd = fopen("rex.wav", "rb"); fseek(fd, 40, SEEK_SET); fread(&frames, sizeof(uint64_t), 1, fd); frames = 800000000; printf("%d\n", frames); // Hardcoded parameters for DSP sample_rate = 44100; // Desc. frequency, Hz sample_bits = 16; // Bits per sample sample_channels = 2; // Stereo // sample_msec = 10; // Size of sample, 100 ms for 10 Hz FFT freq. resolution sample_size = 1024; //sample_size = (int)(sample_rate * (sample_msec / 1000.0F)); sample_buffer_size = sample_size * sample_bits/8 * sample_channels; sample_buffer = (celt_int16 *) calloc(sample_buffer_size, sizeof(char)); encoded_buffer = (unsigned char *) calloc(sample_buffer_size, sizeof(char)); out_buffer = (double *) calloc(sample_buffer_size / (sample_bits/8), sizeof(double)); device = aout_init(); cm = celt_mode_create(sample_rate, sample_size, NULL); //printf("1\n"); ce = celt_encoder_create(cm, sample_channels, NULL); cd = celt_decoder_create(cm, sample_channels, NULL); //printf("2\n"); celt_encoder_ctl(ce, CELT_SET_COMPLEXITY(10)); celt_encoder_ctl(ce, CELT_SET_PREDICTION(2)); celt_encoder_ctl(ce, CELT_SET_VBR_RATE(160000)); // Reading util end of file (frames - number of frames in WAV) badbytes = totalbytes = lostbytes = 0; for (i = 0; i < (sample_rate / sample_size) * (frames / (sample_rate * sample_channels * (sample_bits / 8))) ; ++i) { // Reading sample from file read_sample_into_buffer(fd, (char *)sample_buffer, sample_size); printf("%d %d \n", (sample_rate / sample_size) * (frames / (sample_rate * sample_channels * (sample_bits / 8))) , i); printf("Sample_buffer_size: %d\n", sample_buffer_size); compressed = celt_encode(ce, sample_buffer, NULL, encoded_buffer, 1024); printf("Compressed bytes: %d, bitrate: %d kbps\n", compressed, (int)((sample_rate * sample_bits * sample_channels / 1024) * (compressed * 1.0F / sample_buffer_size))); memset(sample_buffer, 0, sample_buffer_size); if (rand() > (int)(0.95 * RAND_MAX)) { bad = rand() % (compressed / 4) + 5; printf("Packet error, wiped %d bytes\n", bad); memcpy(encoded_buffer + 2 * (compressed / 3) + 4, encoded_buffer, bad); badbytes += bad; } if (rand() > (int)(0.0075 * RAND_MAX)) { celt_decode(cd, encoded_buffer, compressed, sample_buffer); aout_play(device, sample_buffer, sample_buffer_size); } else { usleep(sample_size * 1000000 / sample_rate); printf("Packet was lost\n"); lostbytes += compressed; } totalbytes += compressed; printf("Total kbytes: %d, lost: %d (%.3f proc), damaged: %d (%.3f proc)\n", totalbytes / 1024, lostbytes / 1024, lostbytes * 100.0F / totalbytes , badbytes / 1024, badbytes * 100.0F / totalbytes ); } aout_close(device); return 0; }
int main(int argc, char **argv) { int sd, rc, n, tmp; char msg[MAX_MSG]; int nfds; int send_timestamp = 0; int recv_started = 0; struct pollfd *pfds; struct alsa_dev *dev; CELTEncoder *enc_state; CELTDecoder *dec_state; CELTMode *mode; struct sched_param param; JitterBuffer *jitter; SpeexEchoState *echo_state; char mac_own[6], mac_remote[6]; if (argc != 4) panic("Usage %s plughw:0,0 <lmac in xx:xx:xx:xx:xx:xx> <rmac>\n", argv[0]); register_signal(SIGINT, sighandler); hack_mac(mac_own, argv[2], strlen(argv[2])); hack_mac(mac_remote, argv[3], strlen(argv[3])); sd = socket(AF_LANA, SOCK_RAW, 0); if (sd < 0) panic("%s: cannot open socket \n", argv[0]); printf("If ready hit key!\n"); //user must do binding getchar(); dev = alsa_open(argv[1], SAMPLING_RATE, CHANNELS, FRAME_SIZE); mode = celt_mode_create(SAMPLING_RATE, FRAME_SIZE, NULL); enc_state = celt_encoder_create(mode, CHANNELS, NULL); dec_state = celt_decoder_create(mode, CHANNELS, NULL); param.sched_priority = sched_get_priority_min(SCHED_FIFO); if (sched_setscheduler(0, SCHED_FIFO, ¶m)) whine("sched_setscheduler error!\n"); /* Setup all file descriptors for poll()ing */ nfds = alsa_nfds(dev); pfds = xmalloc(sizeof(*pfds) * (nfds + 1)); alsa_getfds(dev, pfds, nfds); pfds[nfds].fd = sd; pfds[nfds].events = POLLIN; /* Setup jitter buffer using decoder */ jitter = jitter_buffer_init(FRAME_SIZE); tmp = FRAME_SIZE; jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MARGIN, &tmp); /* Echo canceller with 200 ms tail length */ echo_state = speex_echo_state_init(FRAME_SIZE, 10 * FRAME_SIZE); tmp = SAMPLING_RATE; speex_echo_ctl(echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp); register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO); alsa_start(dev); printf("ALSA started!\n"); itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = interval; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = interval; setitimer(ITIMER_REAL, &itimer, NULL); while (!sigint) { poll(pfds, nfds + 1, -1); /* Received packets */ if (pfds[nfds].revents & POLLIN) { memset(msg, 0, MAX_MSG); n = recv(sd, msg, MAX_MSG, 0); if (n <= 0) goto do_alsa; pkts_in++; int recv_timestamp; memcpy(&recv_timestamp, msg, sizeof(recv_timestamp)); JitterBufferPacket packet; packet.data = msg+4/*+6+6+2*/; packet.len = n-4/*-6-6-2*/; packet.timestamp = recv_timestamp; packet.span = FRAME_SIZE; packet.sequence = 0; /* Put content of the packet into the jitter buffer, except for the pseudo-header */ jitter_buffer_put(jitter, &packet); recv_started = 1; } do_alsa: /* Ready to play a frame (playback) */ if (alsa_play_ready(dev, pfds, nfds)) { short pcm[FRAME_SIZE * CHANNELS] = {0}; if (recv_started) { JitterBufferPacket packet; /* Get audio from the jitter buffer */ packet.data = msg; packet.len = MAX_MSG; jitter_buffer_tick(jitter); jitter_buffer_get(jitter, &packet, FRAME_SIZE, NULL); if (packet.len == 0) packet.data=NULL; celt_decode(dec_state, (const unsigned char *) packet.data, packet.len, pcm); } /* Playback the audio and reset the echo canceller if we got an underrun */ alsa_write(dev, pcm, FRAME_SIZE); // if (alsa_write(dev, pcm, FRAME_SIZE)) // speex_echo_state_reset(echo_state); /* Put frame into playback buffer */ // speex_echo_playback(echo_state, pcm); } /* Audio available from the soundcard (capture) */ if (alsa_cap_ready(dev, pfds, nfds)) { short pcm[FRAME_SIZE * CHANNELS]; //pcm2[FRAME_SIZE * CHANNELS]; char outpacket[MAX_MSG]; alsa_read(dev, pcm, FRAME_SIZE); /* Perform echo cancellation */ // speex_echo_capture(echo_state, pcm, pcm2); // for (i = 0; i < FRAME_SIZE * CHANNELS; ++i) // pcm[i] = pcm2[i]; celt_encode(enc_state, pcm, NULL, (unsigned char *) (outpacket+4+6+6+2), PACKETSIZE); /* Pseudo header: four null bytes and a 32-bit timestamp; XXX hack */ memcpy(outpacket,mac_remote,6); memcpy(outpacket+6,mac_own,6); outpacket[6+6] = (uint8_t) 0xac; outpacket[6+6+1] = (uint8_t) 0xdc; memcpy(outpacket+6+6+2, &send_timestamp, sizeof(send_timestamp)); send_timestamp += FRAME_SIZE; rc = sendto(sd, outpacket, PACKETSIZE+4+6+6+2, 0, NULL, 0); if (rc < 0) panic("cannot send to socket"); pkts_out++; } } itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itimer, NULL); close(sd); return 0; }