/* * Call with audio and video on both sides. Alice calls Bob. */ CALL_AND_START_LOOP(TypeVideo, TypeVideo) { /* Both send */ payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 1000, sample_payload, frame_size); if ( payload_size < 0 ) { ck_assert_msg ( 0, "Failed to encode payload" ); } toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); payload_size = toxav_prepare_audio_frame(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, 1000, sample_payload, frame_size); if ( payload_size < 0 ) { ck_assert_msg ( 0, "Failed to encode payload" ); } toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); // toxav_send_video(status_control.Alice.av, status_control.Alice.call_index, sample_image); // toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ step++; /* This terminates the loop */ toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); /* Call over Alice hangs up */ toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); } }
void read_device_callback (const int16_t* captured, uint32_t size, void* data) { int32_t call_index = *((int32_t*)data); /* TODO: Or pass an array of call_idx's */ uint8_t encoded_payload[RTP_PAYLOAD_SIZE]; int32_t payload_size = toxav_prepare_audio_frame(ASettins.av, call_index, encoded_payload, RTP_PAYLOAD_SIZE, captured, size); if ( payload_size <= 0 || toxav_send_audio(ASettins.av, call_index, encoded_payload, payload_size) < 0 ) { /*fprintf(stderr, "Could not encode audio packet\n");*/ } }
void Core::sendCallAudio(int32_t callId, ToxAv* toxav) { if (!calls[callId].active) return; if (calls[callId].muteMic || !Audio::isInputReady()) { calls[callId].sendAudioTimer->start(); return; } const int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000 * av_DefaultSettings.audio_channels; const int bufsize = framesize * 2 * av_DefaultSettings.audio_channels; uint8_t buf[bufsize]; if (Audio::tryCaptureSamples(buf, framesize)) { #ifdef QTOX_FILTER_AUDIO if (Settings::getInstance().getFilterAudio()) { if (!filterer[callId]) { filterer[callId] = new AudioFilterer(); filterer[callId]->startFilter(48000); } // is a null op #ifndef ALC_LOOPBACK_CAPTURE_SAMPLES Audio::getEchoesToFilter(filterer[callId], framesize); filterer[callId]->filterAudio((int16_t*) buf, framesize); } else if (filterer[callId]) { delete filterer[callId]; filterer[callId] = nullptr; } #endif uint8_t dest[bufsize]; int r; if ((r = toxav_prepare_audio_frame(toxav, callId, dest, framesize*2, (int16_t*)buf, framesize)) < 0) { qDebug() << "Core: toxav_prepare_audio_frame error"; calls[callId].sendAudioTimer->start(); return; } if ((r = toxav_send_audio(toxav, callId, dest, r)) < 0) qDebug() << "Core: toxav_send_audio error"; } calls[callId].sendAudioTimer->start(); }
/* Media change */ CALL_AND_START_LOOP(TypeAudio, TypeAudio) { /* Both send */ payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 1000, sample_payload, frame_size); if ( payload_size < 0 ) { ck_assert_msg ( 0, "Failed to encode payload" ); } toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); payload_size = toxav_prepare_audio_frame(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, 1000, sample_payload, frame_size); if ( payload_size < 0 ) { ck_assert_msg ( 0, "Failed to encode payload" ); } toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); /* Wait 2 seconds and change transmission type */ if (time(NULL) - times_they_are_a_changin > 2) { times_they_are_a_changin = time(NULL); muhcaps.audio_bitrate ++; toxav_change_settings(status_control.Alice.av, status_control.Alice.call_index, &muhcaps); } if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ step++; /* This terminates the loop */ toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); /* Call over Alice hangs up */ toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); } }
void Core::sendCallAudio(int callId, ToxAv* toxav) { if (!calls[callId].active) return; if (calls[callId].muteMic) { calls[callId].sendAudioTimer->start(); return; } int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000; uint8_t buf[framesize*2], dest[framesize*2]; bool frame = false; ALint samples; alcGetIntegerv(alInDev, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= framesize) { alcCaptureSamples(alInDev, buf, framesize); frame = 1; } if(frame) { int r; if((r = toxav_prepare_audio_frame(toxav, callId, dest, framesize*2, (int16_t*)buf, framesize)) < 0) { qDebug() << "Core: toxav_prepare_audio_frame error"; calls[callId].sendAudioTimer->start(); return; } if((r = toxav_send_audio(toxav, callId, dest, r)) < 0) qDebug() << "Core: toxav_send_audio error"; } calls[callId].sendAudioTimer->start(); }
void *in_thread_call (void *arg) { #define call_print(call, what, args...) printf("[%d] " what "\n", call, ##args) ACall *this_call = arg; uint64_t start = 0; int step = 0; int call_idx; const int frame_size = (av_DefaultSettings.audio_sample_rate * av_DefaultSettings.audio_frame_duration / 1000); int16_t sample_payload[frame_size]; randombytes((uint8_t *)sample_payload, sizeof(int16_t) * frame_size); uint8_t prepared_payload[RTP_PAYLOAD_SIZE]; register_callbacks(this_call->Caller.av, &status_control); register_callbacks(this_call->Callee.av, arg); /* NOTE: CALLEE WILL ALWAHYS NEED CALL_IDX == 0 */ pthread_mutex_lock(&muhmutex); while (call_running[this_call->idx]) { pthread_mutex_unlock(&muhmutex); switch ( step ) { case 0: /* CALLER */ toxav_call(this_call->Caller.av, &call_idx, this_call->Callee.id, &av_DefaultSettings, 10); call_print(call_idx, "Calling ..."); step++; break; case 1: /* CALLEE */ pthread_mutex_lock(&muhmutex); if (this_call->Caller.status == Ringing) { call_print(call_idx, "Callee answers ..."); pthread_mutex_unlock(&muhmutex); toxav_answer(this_call->Callee.av, 0, &av_DefaultSettings); step++; start = time(NULL); pthread_mutex_lock(&muhmutex); } pthread_mutex_unlock(&muhmutex); break; case 2: /* Rtp transmission */ pthread_mutex_lock(&muhmutex); if (this_call->Caller.status == InCall) { /* I think this is okay */ call_print(call_idx, "Sending rtp ..."); pthread_mutex_unlock(&muhmutex); c_sleep(1000); /* We have race condition here */ toxav_prepare_transmission(this_call->Callee.av, 0, 1); toxav_prepare_transmission(this_call->Caller.av, call_idx, 1); int payload_size = toxav_prepare_audio_frame(this_call->Caller.av, call_idx, prepared_payload, RTP_PAYLOAD_SIZE, sample_payload, frame_size); if ( payload_size < 0 ) { ck_assert_msg ( 0, "Failed to encode payload" ); } while (time(NULL) - start < 10) { /* 10 seconds */ /* Both send */ toxav_send_audio(this_call->Caller.av, call_idx, prepared_payload, payload_size); toxav_send_audio(this_call->Callee.av, 0, prepared_payload, payload_size); /* Both receive */ int16_t storage[RTP_PAYLOAD_SIZE]; int recved; c_sleep(20); } step++; /* This terminates the loop */ pthread_mutex_lock(&muhmutex); toxav_kill_transmission(this_call->Callee.av, 0); toxav_kill_transmission(this_call->Caller.av, call_idx); pthread_mutex_unlock(&muhmutex); /* Call over CALLER hangs up */ toxav_hangup(this_call->Caller.av, call_idx); call_print(call_idx, "Hanging up ..."); pthread_mutex_lock(&muhmutex); } pthread_mutex_unlock(&muhmutex); break; case 3: /* Wait for Both to have status ended */ pthread_mutex_lock(&muhmutex); if (this_call->Caller.status == Ended) { pthread_mutex_unlock(&muhmutex); c_sleep(1000); /* race condition */ pthread_mutex_lock(&muhmutex); this_call->Callee.status = Ended; call_running[this_call->idx] = 0; } pthread_mutex_unlock(&muhmutex); break; } c_sleep(20); pthread_mutex_lock(&muhmutex); } pthread_mutex_unlock(&muhmutex); call_print(call_idx, "Call ended successfully!"); pthread_exit(NULL); }
/* * Call with audio and video on both sides. Alice calls Bob. */ CALL_AND_START_LOOP(TypeVideo, TypeVideo) { /* Both send */ payload_size = toxav_prepare_audio_frame(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, 1000, sample_payload, frame_size); if ( payload_size < 0 ) { ck_assert_msg ( 0, "Failed to encode payload" ); } toxav_send_audio(status_control.Alice.av, status_control.Alice.call_index, prepared_payload, payload_size); payload_size = toxav_prepare_audio_frame(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, 1000, sample_payload, frame_size); if ( payload_size < 0 ) { ck_assert_msg ( 0, "Failed to encode payload" ); } toxav_send_audio(status_control.Bob.av, status_control.Bob.call_index, prepared_payload, payload_size); // toxav_send_video(status_control.Alice.av, status_control.Alice.call_index, sample_image); // toxav_send_video(status_control.Bob.av, status_control.Bob.call_index, sample_image); /* Both receive */ int16_t storage[frame_size]; vpx_image_t *video_storage; int recved; /* Payload from Bob */ recved = toxav_recv_audio(status_control.Alice.av, status_control.Alice.call_index, frame_size, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/ } /* Video payload */ // toxav_recv_video(status_control.Alice.av, status_control.Alice.call_index, &video_storage); // // if ( video_storage ) { // /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || // memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || // memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Bob is invalid");*/ // vpx_img_free(video_storage); // } /* Payload from Alice */ recved = toxav_recv_audio(status_control.Bob.av, status_control.Bob.call_index, frame_size, storage); if ( recved ) { /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Alice is invalid");*/ } /* Video payload */ // toxav_recv_video(status_control.Bob.av, status_control.Bob.call_index, &video_storage); // // if ( video_storage ) { // /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || // memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || // memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Alice is invalid");*/ // vpx_img_free(video_storage); // } if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */ step++; /* This terminates the loop */ toxav_kill_transmission(status_control.Alice.av, status_control.Alice.call_index); toxav_kill_transmission(status_control.Bob.av, status_control.Bob.call_index); /* Call over Alice hangs up */ toxav_hangup(status_control.Alice.av, status_control.Alice.call_index); } }
void Cyanide::audio_thread() { return; const char *device_list, *output_device = NULL; //void *audio_device = NULL; bool call[MAX_CALLS] = {0}, preview = 0; bool audio_filtering_enabled; // bool groups_audio[MAX_NUM_GROUPS] = {0}; int perframe = (av_DefaultSettings.audio_frame_duration * av_DefaultSettings.audio_sample_rate) / 1000; uint8_t buf[perframe * 2 * av_DefaultSettings.audio_channels], dest[perframe * 2 * av_DefaultSettings.audio_channels]; memset(buf, 0, sizeof(buf)); uint8_t audio_count = 0; bool record_on = 0; #ifdef AUDIO_FILTERING qDebug() << "Audio Filtering enabled"; #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES qDebug() << "Echo cancellation enabled"; #endif #endif qDebug() << "frame size:" << perframe; device_list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); if(device_list) { output_device = device_list; qDebug() << "Output Device List:"; while(*device_list) { qDebug() << device_list; //postmessage(NEW_AUDIO_OUT_DEVICE, 0, 0, (void*)device_list); device_list += strlen(device_list) + 1; } } device_out = alcOpenDevice(output_device); if(!device_out) { qDebug() << "alcOpenDevice() failed"; return; } int attrlist[] = { ALC_FREQUENCY, av_DefaultSettings.audio_sample_rate, ALC_INVALID }; context = alcCreateContext(device_out, attrlist); if(!alcMakeContextCurrent(context)) { qDebug() << "alcMakeContextCurrent() failed"; alcCloseDevice(device_out); return; } alGenSources(countof(source), source); static ALuint ringSrc[MAX_CALLS]; alGenSources(MAX_CALLS, ringSrc); /* Create buffer to store samples */ ALuint RingBuffer; alGenBuffers(1, &RingBuffer); { float frequency1 = 441.f; float frequency2 = 882.f; int seconds = 4; unsigned sample_rate = 22050; size_t buf_size = seconds * sample_rate * 2; //16 bit (2 bytes per sample) int16_t *samples = (int16_t*)malloc(buf_size * sizeof(int16_t)); if (!samples) return; /*Generate an electronic ringer sound that quickly alternates between two frequencies*/ int index = 0; for(index = 0; index < buf_size; ++index) { if ((index / (sample_rate)) % 4 < 2 ) {//4 second ring cycle, first 2 secondsring, the rest(2 seconds) is silence if((index / 1000) % 2 == 1) { samples[index] = 5000 * sin((2.0 * 3.1415926 * frequency1) / sample_rate * index); //5000=amplitude(volume level). It can be from zero to 32700 } else { samples[index] = 5000 * sin((2.0 * 3.1415926 * frequency2) / sample_rate * index); } } else { samples[index] = 0; } } alBufferData(RingBuffer, AL_FORMAT_MONO16, samples, buf_size, sample_rate); free(samples); } { unsigned int i; for (i = 0; i < MAX_CALLS; ++i) { alSourcei(ringSrc[i], AL_LOOPING, AL_TRUE); alSourcei(ringSrc[i], AL_BUFFER, RingBuffer); } } #ifdef AUDIO_FILTERING Filter_Audio *f_a = NULL; #endif while(loop == LOOP_RUN || loop == LOOP_SUSPEND) { #ifdef AUDIO_FILTERING if (!f_a && audio_filtering_enabled) { f_a = new_filter_audio(av_DefaultSettings.audio_sample_rate); if (!f_a) { audio_filtering_enabled = 0; qDebug() << "filter audio failed"; } else { qDebug() << "filter audio on"; } } else if (f_a && !audio_filtering_enabled) { kill_filter_audio(f_a); f_a = NULL; qDebug() << "filter audio off"; } #else if (audio_filtering_enabled) audio_filtering_enabled = 0; #endif bool sleep = 1; if(record_on) { ALint samples; alcGetIntegerv(device_in, ALC_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= perframe) { alcCaptureSamples(device_in, buf, perframe); if (samples >= perframe * 2) { sleep = 0; } } } #ifdef AUDIO_FILTERING #ifdef ALC_LOOPBACK_CAPTURE_SAMPLES if (f_a && audio_filtering_enabled) { ALint samples; alcGetIntegerv(device_out, ALC_LOOPBACK_CAPTURE_SAMPLES, sizeof(samples), &samples); if(samples >= perframe) { int16_t buffer[perframe]; alcCaptureSamplesLoopback(device_out, buffer, perframe); pass_audio_output(f_a, buffer, perframe); set_echo_delay_ms(f_a, 5); if (samples >= perframe * 2) { sleep = 0; } } } #endif #endif #ifdef AUDIO_FILTERING if (f_a && filter_audio(f_a, (int16_t*)buf, perframe) == -1) { qDebug() << "filter audio error"; } #endif if(preview) { audio_play(0, (int16_t*)buf, perframe, av_DefaultSettings.audio_channels, av_DefaultSettings.audio_sample_rate); } int i; for(i = 0; i < MAX_CALLS; i++) { if(call[i]) { int r; if((r = toxav_prepare_audio_frame(toxav, i, dest, sizeof(dest), (const int16_t*)buf, perframe)) < 0) { qDebug() << "toxav_prepare_audio_frame error" << r; continue; } if((r = toxav_send_audio(toxav, i, dest, r)) < 0) { qDebug() << "toxav_send_audio error" << r; } } } if (sleep) { usleep(5000); } } #ifdef AUDIO_FILTERING kill_filter_audio(f_a); #endif //missing some cleanup ? alDeleteSources(MAX_CALLS, ringSrc); alDeleteSources(countof(source), source); alDeleteBuffers(1, &RingBuffer); if(device_in) { if(record_on) { alcCaptureStop(device_in); } alcCaptureCloseDevice(device_in); } alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device_out); }