static void handle_audio_event(struct iax_event *e, int callNo) { int total_consumed = 0; short fr[4096]; const int fr_samples = sizeof(fr) / sizeof(short); int samples, format; #ifdef WIN32 int cycles_max = 100; //fd: #endif struct iaxc_call *call; if ( callNo < 0 ) return; call = &calls[callNo]; if ( callNo != selected_call ) { /* drop audio for unselected call? */ return; } if ( audio_prefs & IAXC_AUDIO_PREF_RECV_DISABLE) { /* just drop silently incoming audio frames */ return; } samples = fr_samples; format = call->format & IAXC_AUDIO_FORMAT_MASK; do { int bytes_decoded; int mainbuf_delta = fr_samples - samples; bytes_decoded = audio_decode_audio(call, fr, e->data + total_consumed, e->datalen - total_consumed, format, &samples); if ( bytes_decoded < 0 ) { iaxci_usermsg(IAXC_STATUS, "Bad or incomplete voice packet. Unable to decode. dropping"); return; } /* Pass encoded audio back to the app if required */ if ( audio_prefs & IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED ) iaxci_do_audio_callback(callNo, e->ts, IAXC_SOURCE_REMOTE, 1, format & IAXC_AUDIO_FORMAT_MASK, e->datalen - total_consumed, e->data + total_consumed); #ifdef WIN32 //fd: start: for some reason it loops here. Try to avoid it cycles_max--; if ( cycles_max < 0 ) { iaxc_millisleep(0); } //fd: end #endif total_consumed += bytes_decoded; if ( audio_prefs & IAXC_AUDIO_PREF_RECV_REMOTE_RAW ) { // audio_decode_audio returns the number of samples. // We are using 16 bit samples, so we need to double // the number to obtain the size in bytes. // format will also be 0 since this is raw audio int size = (fr_samples - samples - mainbuf_delta) * 2; iaxci_do_audio_callback(callNo, e->ts, IAXC_SOURCE_REMOTE, 0, 0, size, (unsigned char *)fr); } if ( iaxci_audio_output_mode ) continue; if (!test_mode) audio_driver.output(&audio_driver, fr, fr_samples - samples - mainbuf_delta); } while ( total_consumed < e->datalen ); }
static int service_audio() { /* TODO: maybe we shouldn't allocate 8kB on the stack here. */ short buf [4096]; int want_send_audio = selected_call >= 0 && ((calls[selected_call].state & IAXC_CALL_STATE_OUTGOING) || (calls[selected_call].state & IAXC_CALL_STATE_COMPLETE)); //&& !(audio_prefs & IAXC_AUDIO_PREF_SEND_DISABLE); int want_local_audio = (audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_RAW) || (audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_ENCODED); //fprintf(stdout, "service_audio() => want_send_audio=%d/want_local_audio=%d\n", want_send_audio, want_local_audio); if ( want_local_audio || want_send_audio ) { for ( ;; ) { int to_read; int cmin; audio_driver.start(&audio_driver); /* use codec minimum if higher */ cmin = want_send_audio && calls[selected_call].encoder ? calls[selected_call].encoder->minimum_frame_size : 1; to_read = cmin > minimum_outgoing_framesize ? cmin : minimum_outgoing_framesize; /* Round up to the next multiple */ if ( to_read % cmin ) to_read += cmin - (to_read % cmin); if ( to_read > (int)(sizeof(buf) / sizeof(short)) ) { fprintf(stderr, "internal error: to_read > sizeof(buf)\n"); exit(1); } /* Currently pa gives us either all the bits we ask for or none */ if ( audio_driver.input(&audio_driver, buf, &to_read) ) { iaxci_usermsg(IAXC_ERROR, "ERROR reading audio\n"); break; } /* Frame was not available */ if ( !to_read ) break; if ( audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_RAW ) iaxci_do_audio_callback(selected_call, 0, IAXC_SOURCE_LOCAL, 0, 0, to_read * 2, (unsigned char *)buf); if (( want_send_audio ) && (!(audio_prefs & IAXC_AUDIO_PREF_SEND_DISABLE))) audio_send_encoded_audio(&calls[selected_call], selected_call, buf, calls[selected_call].format & IAXC_AUDIO_FORMAT_MASK, to_read); } } else { static int i = 0; audio_driver.stop(&audio_driver); /*! \deprecated Q: Why do we continuously send IAXC_EVENT_LEVELS events when there is no selected call? A: So that certain users of iaxclient do not have to reset their vu meters when a call ends -- they can just count on getting level callbacks. This is a bit of a hack so any applications relying on this behavior should maybe be changed. */ if ( i++ % 50 == 0 ) iaxci_do_levels_callback(AUDIO_ENCODE_SILENCE_DB, AUDIO_ENCODE_SILENCE_DB); } return 0; }
int audio_send_encoded_audio(struct iaxc_call *call, int callNo, void *data, int format, int samples) { unsigned char outbuf[1024]; int outsize = 1024; int silent; int insize = samples; /* update last input timestamp */ timeLastInput = iax_tvnow(); silent = input_postprocess(data, insize, 8000); if(silent) { if(!call->tx_silent) { /* send a Comfort Noise Frame */ call->tx_silent = 1; if ( iaxci_filters & IAXC_FILTER_CN ) iax_send_cng(call->session, 10, NULL, 0); } return 0; /* poof! no encoding! */ } /* we're going to send voice now */ call->tx_silent = 0; /* destroy encoder if it is incorrect type */ if(call->encoder && call->encoder->format != format) { call->encoder->destroy(call->encoder); call->encoder = NULL; } /* just break early if there's no format defined: this happens for the * first couple of frames of new calls */ if(format == 0) return 0; /* create encoder if necessary */ if(!call->encoder) { call->encoder = create_codec(format); } if(!call->encoder) { /* ERROR: no codec */ fprintf(stderr, "ERROR: Codec could not be created: %d\n", format); return 0; } if(call->encoder->encode(call->encoder, &insize, (short *)data, &outsize, outbuf)) { /* ERROR: codec error */ fprintf(stderr, "ERROR: encode error: %d\n", format); return 0; } if(samples-insize == 0) { fprintf(stderr, "ERROR encoding (no samples output (samples=%d)\n", samples); return -1; } // Send the encoded audio data back to the app if required // TODO: fix the stupid way in which the encoded audio size is returned if ( iaxc_get_audio_prefs() & IAXC_AUDIO_PREF_RECV_LOCAL_ENCODED ) iaxci_do_audio_callback(callNo, 0, IAXC_SOURCE_LOCAL, 1, call->encoder->format & IAXC_AUDIO_FORMAT_MASK, sizeof(outbuf) - outsize, outbuf); if(iax_send_voice(call->session,format, outbuf, sizeof(outbuf) - outsize, samples-insize) == -1) { fprintf(stderr, "Failed to send voice! %s\n", iax_errstr); return -1; } return 0; }