void IAXVoIPLink::sendAudioFromMic() { for (CallMap::const_iterator iter = callMap_.begin(); iter != callMap_.end() ; ++iter) { IAXCall *currentCall = dynamic_cast<IAXCall*>(iter->second); if (!currentCall or currentCall->getState() != Call::ACTIVE) continue; int codecType = currentCall->getAudioCodec(); sfl::AudioCodec *audioCodec = static_cast<sfl::AudioCodec *>(Manager::instance().audioCodecFactory.getCodec(codecType)); if (!audioCodec) continue; Manager::instance().getMainBuffer()->setInternalSamplingRate(audioCodec->getClockRate()); unsigned int mainBufferSampleRate = Manager::instance().getMainBuffer()->getInternalSamplingRate(); // we have to get 20ms of data from the mic *20/1000 = /50 // rate/50 shall be lower than IAX__20S_48KHZ_MAX int bytesNeeded = mainBufferSampleRate * 20 / 1000 * sizeof(SFLDataFormat); if (Manager::instance().getMainBuffer()->availForGet(currentCall->getCallId()) < bytesNeeded) continue; // Get bytes from micRingBuffer to data_from_mic int bytes = Manager::instance().getMainBuffer()->getData(decData_, bytesNeeded, currentCall->getCallId()); int samples = bytes / sizeof(SFLDataFormat); int compSize; unsigned int audioRate = audioCodec->getClockRate(); int outSamples; SFLDataFormat *in; if (audioRate != mainBufferSampleRate) { converter_.resample(decData_, resampledData_, ARRAYSIZE(resampledData_), audioRate, mainBufferSampleRate, samples); in = resampledData_; outSamples = 0; } else { outSamples = samples; in = decData_; } compSize = audioCodec->encode(encodedData_, in, DEC_BUFFER_SIZE); if (currentCall->session and bytes > 0) { ost::MutexLock m(mutexIAX_); if (iax_send_voice(currentCall->session, currentCall->format, encodedData_, compSize, outSamples) == -1) ERROR("IAX: Error sending voice data."); } } }
EXPORT int iaxc_push_audio(void *data, unsigned int size, unsigned int samples) { struct iaxc_call *call; if ( selected_call < 0 ) return -1; call = &calls[selected_call]; if ( audio_prefs & IAXC_AUDIO_PREF_SEND_DISABLE ) return 0; //fprintf(stderr, "iaxc_push_audio: sending audio size %d\n", size); if ( iax_send_voice(call->session, call->format, data, size, samples) == -1 ) { fprintf(stderr, "iaxc_push_audio: failed to send audio frame of size %d on call %d\n", size, selected_call); return -1; } return 0; }
int send_encoded_audio(struct iaxc_call *call, void *data, int format, int samples) { unsigned char outbuf[1024]; int outsize = 1024; int silent; int insize = samples; //fprintf(stderr, "in encode_audio, format=%d\n", format); /* update last input timestamp */ gettimeofday( &timeLastInput, NULL ) ; silent = iaxc_input_postprocess(data,insize,8000); if(silent) { if(!call->tx_silent) { /* send a Comfort Noise Frame */ call->tx_silent = 1; if(iaxc_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; } if(iax_send_voice(call->session,format, outbuf, 1024-outsize, samples-insize) == -1) { puts("Failed to send voice!"); return -1; } 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; }
int main(int argc, char *argv[]) { int port; int netfd; int c, h=0, m, regm; FILE *f; int fd = STDIN_FILENO; char rcmd[RBUFSIZE]; fd_set readfd; fd_set writefd; struct timeval timer; struct timeval *timerptr = NULL; gsm_frame fo; load_options(); if (!strlen(callerid)) gethostname(callerid, sizeof(callerid)); signal(SIGHUP, sighandler); signal(SIGINT, sighandler); if ( !(f = fdopen(fd, "w+"))) { fprintf(stderr, "Unable to create file on fd %d\n", fd); return -1; } if ( (audiofd = audio_setup(audiodev)) == -1) { fprintf(stderr, "Fatal error: failed to open sound device"); return -1; } if ( (port = iax_init(0) < 0)) { fprintf(stderr, "Fatal error: failed to initialize iax with port %d\n", port); return -1; } iax_set_formats(AST_FORMAT_GSM); netfd = iax_get_fd(); check_iax_register(); fprintf(f, "Text Based Telephony Client.\n\n"); issue_prompt(f); timer.tv_sec = 0; timer.tv_usec = 0; while(1) { FD_ZERO(&readfd); FD_ZERO(&writefd); FD_SET(fd, &readfd); if(fd > h) h = fd; if(answered_call && !writeonly) { FD_SET(audiofd, &readfd); if(audiofd > h) h = audiofd; } if (cursound > -1) { FD_SET(audiofd, &writefd); if (audiofd > h) h = audiofd; } FD_SET(netfd, &readfd); if(netfd > h) h = netfd; if ( (c = select(h+1, &readfd, &writefd, 0, timerptr)) >= 0) { if(FD_ISSET(fd, &readfd)) { if ( ( fgets(&*rcmd, 256, f))) { rcmd[strlen(rcmd)-1] = 0; parse_args(f, &*rcmd); } else fprintf(f, "Fatal error: failed to read data!\n"); issue_prompt(f); } if(answered_call) { if(FD_ISSET(audiofd, &readfd)) { static int ret, rlen = 0; static short rbuf[FRAME_SIZE]; if ( (ret = read(audiofd, rbuf + rlen, 2 * (FRAME_SIZE-rlen))) == -1) { puts("Failed to read audio."); return -1; } rlen += ret/2; if(rlen == FRAME_SIZE) { rlen = 0; if(!most_recent_answer->gsmout) most_recent_answer->gsmout = gsm_create(); gsm_encode(most_recent_answer->gsmout, rbuf, fo); if(iax_send_voice(most_recent_answer->session, AST_FORMAT_GSM, (char *)fo, sizeof(fo)) == -1) puts("Failed to send voice!"); } } } do_iax_event(f); m = iax_time_to_next_event(); if(m > -1) { timerptr = &timer; timer.tv_sec = m /1000; timer.tv_usec = (m % 1000) * 1000; } else timerptr = 0; regm = check_iax_timeout(); if (!timerptr || (m > regm)) { timerptr = &timer; timer.tv_sec = regm /1000; timer.tv_usec = (regm % 1000) * 1000; } if (FD_ISSET(audiofd, &writefd)) { send_sound(audiofd); } } else { if(errno == EINTR) continue; fprintf(stderr, "Fatal error in select(): %s\n", strerror(errno)); return -1; } } return 0; }