Example #1
0
    /*
     * 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);
        }
    }
    /*
     * Call with audio and video on both sides. Alice calls Bob.
     */
    CALL_AND_START_LOOP(TypeVideo, TypeVideo) {
        /* Both send */
        toxav_send_audio(status_control.Alice.av, sample_payload, 10);
        toxav_send_video(status_control.Alice.av, sample_image);

        toxav_send_audio(status_control.Bob.av, sample_payload, 10);
        toxav_send_video(status_control.Bob.av, sample_image);

        /* Both receive */
        int16_t storage[10];
        vpx_image_t *video_storage;
        int recved;

        /* Payload from Bob */
        recved = toxav_recv_audio(status_control.Alice.av, 10, storage);

        if ( recved ) {
            /*ck_assert_msg(recved == 10 && memcmp(storage, sample_payload, 10) == 0, "Payload from Bob is invalid");*/
            memset(storage, 0, 10);
        }

        /* Video payload */
        toxav_recv_video(status_control.Alice.av, &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");*/
        }




        /* Payload from Alice */
        recved = toxav_recv_audio(status_control.Bob.av, 10, 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, &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");*/
        }


        if (time(NULL) - cur_time > 10) { /* Transmit for 10 seconds */
            step++; /* This terminates the loop */
            toxav_kill_transmission(status_control.Alice.av);
            toxav_kill_transmission(status_control.Bob.av);

            /* Call over Alice hangs up */
            toxav_hangup(status_control.Alice.av);
        }
    }
Example #3
0
void *encode_audio_thread(void *arg)
{
    INFO("Started encode audio thread!");
    av_session_t *_phone = arg;
    _phone->running_encaud = 1;

    int ret = 0;
    int16_t frame[4096];
    int frame_size = AUDIO_FRAME_SIZE;
    ALint sample = 0;
    alcCaptureStart((ALCdevice *)_phone->audio_capture_device);
    while (_phone->running_encaud) {
        
        alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
        
        if (sample >= frame_size) {
            alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size);

            ret = toxav_send_audio(_phone->av, frame, frame_size);

            if (ret < 0) printf("Could not encode or send audio packet\n");

        } else {
            usleep(1000);
        }
    }

    /* clean up codecs *
    pthread_mutex_lock(&cs->ctrl_mutex);* /
    alcCaptureStop((ALCdevice*)_phone->audio_capture_device);
    alcCaptureCloseDevice((ALCdevice*)_phone->audio_capture_device);
    / *pthread_mutex_unlock(&cs->ctrl_mutex);*/
    _phone->running_encaud = -1;
    pthread_exit ( NULL );
}
Example #4
0
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");*/
    }
}
Example #5
0
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();
}
Example #6
0
    /* 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);
        }
    }
Example #7
0
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();
}
Example #8
0
void *one_threaded_audio(void *arg)
{
    INFO("Started audio thread!");
    av_session_t *_phone = arg;
    _phone->running_decaud = 1;
    
    //int recved_size;
    //uint8_t dest [RTP_PAYLOAD_SIZE];
    
    int frame_size = AUDIO_FRAME_SIZE;
    
    int16_t frame[4096];
    ALint sample = 0;
    alcCaptureStart((ALCdevice *)_phone->audio_capture_device);
    
    ALCdevice *dev;
    ALCcontext *ctx;
    ALuint source, *buffers;
    dev = alcOpenDevice(NULL);
    ctx = alcCreateContext(dev, NULL);
    alcMakeContextCurrent(ctx);
    int openal_buffers = 5;
    
    buffers = calloc(sizeof(ALuint) * openal_buffers, 1);
    alGenBuffers(openal_buffers, buffers);
    alGenSources((ALuint)1, &source);
    alSourcei(source, AL_LOOPING, AL_FALSE);
    
    ALuint buffer;
    ALint ready;
    
    uint16_t zeros[frame_size];
    memset(zeros, 0, frame_size);
    int16_t PCM[frame_size];
    
    int i;
    
    for (i = 0; i < openal_buffers; ++i) {
        alBufferData(buffers[i], AL_FORMAT_MONO16, zeros, frame_size, 48000);
    }
    
    alSourceQueueBuffers(source, openal_buffers, buffers);
    alSourcePlay(source);
    
    if (alGetError() != AL_NO_ERROR) {
        fprintf(stderr, "Error starting audio\n");
        goto ending;
    }
    
    int dec_frame_len;
    
    while (_phone->running_decaud) {
        
        // combo
        alcGetIntegerv((ALCdevice *)_phone->audio_capture_device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
        
        // record and send        
        if (sample >= frame_size) {
            alcCaptureSamples((ALCdevice *)_phone->audio_capture_device, frame, frame_size);
            
            if (toxav_send_audio(_phone->av, frame, frame_size) < 0) 
                printf("Could not encode or send audio packet\n");
            
        } else  {
            usleep(5000);
        }
        
        // play received
        
        alGetSourcei(source, AL_BUFFERS_PROCESSED, &ready);
        
        if (ready <= 0)
            continue;
        
        dec_frame_len = toxav_recv_audio(_phone->av, frame_size, PCM);
        
        /* Play the packet */
        if (dec_frame_len > 0) {
            alSourceUnqueueBuffers(source, 1, &buffer);
            alBufferData(buffer, AL_FORMAT_MONO16, PCM, dec_frame_len * 2 * 1, 48000);
            int error = alGetError();
            
            if (error != AL_NO_ERROR) {
                fprintf(stderr, "Error setting buffer %d\n", error);
                break;
            }
            
            alSourceQueueBuffers(source, 1, &buffer);
            
            if (alGetError() != AL_NO_ERROR) {
                fprintf(stderr, "Error: could not buffer audio\n");
                break;
            }
            
            alGetSourcei(source, AL_SOURCE_STATE, &ready);
            
            if (ready != AL_PLAYING) alSourcePlay(source);
        }
        
        usleep(1000);
    }
    
    
    ending:
    _phone->running_decaud = -1;
    
    pthread_exit ( NULL );
}
Example #9
0
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);
}
Example #10
0
    /*
     * 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);
        }
    }
Example #11
0
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);
}