将iaxclient配置为从/发送音频到缓冲区而不是音频设备

16

我正在尝试编写一个连接到Asterisk服务器的C++程序(如果有人知道更好的(IAX / SIP)替代方案,Python也可以),连接后,它应该监听音频并处理它。它还应该发送音频回来。我正在使用https://sourceforge.net/projects/iaxclient/完成这一点(请注意,有几个版本(测试版,常规发布版,svn版本)它们都有不同的行为)。

现在,如果我正确理解库代码,则它可以调用带有事件的回调函数。其中一个事件是IAXC_EVENT_AUDIO。在IAXC_EVENT_AUDIO的结构中,有一个方向;传入的或传出的。这就是我迷失的地方:使用某些版本的iaxclient,我只接收到IAXC_SOURCE_REMOTE消息,而有些则两者都有。而如果我切换到测试模式(应该仅禁用音频设备),我经常根本没有接收到任何消息。当我同时接收IAXC_SOURCE_LOCAL和IAXC_SOURCE_REMOTE时,我尝试将这些事件的缓冲区设置为随机数据,但是对方根本无法收到它(我将其设置为原始模式)。

是否有人有建议如何解决这个问题?

我的测试代码如下:

#include <iaxclient.h>
#include <unistd.h>

int iaxc_event_callback(iaxc_event e)
{
    if (e.type == IAXC_EVENT_TEXT) {
        printf("text\n");
    }
    else if (e.type == IAXC_EVENT_LEVELS) {
        printf("level\n");
    }
    else if (e.type == IAXC_EVENT_STATE) {
        struct iaxc_ev_call_state *st = iaxc_get_event_state(&e);
        printf("\tcallno %d state %d format %d remote %s(%s)\n", st->callNo, st->state, st->format,st->remote, st->remote_name);
        iaxc_key_radio(st->callNo);
    }
    else if (e.type == IAXC_EVENT_NETSTAT) {
        printf("\tcallno %d rtt %d\n", e.ev.netstats.callNo, e.ev.netstats.rtt);
    }
    else if (e.type == IAXC_EVENT_AUDIO) {
        printf("\t AUDIO!!!! %d %u %d\n", e.ev.audio.source, e.ev.audio.ts, e.ev.audio.size);

        for(int i=0; i<e.ev.audio.size; i++)
            printf("%02x ", e.ev.audio.data[i]);
        printf("\n");
    }
    else {
        printf("type: %d\n", e.type);
    }

    return 1;
}

int main(int argc, char *argv[])
{
    iaxc_set_test_mode(1);
    printf("init %d\n", iaxc_initialize(1));

    iaxc_set_formats(IAXC_FORMAT_SPEEX, IAXC_FORMAT_SPEEX);

    iaxc_set_event_callback(iaxc_event_callback);
    printf("get audio pref %d\n", iaxc_get_audio_prefs());
    //printf("set audio pref %d\n", iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED));
    printf("set audio pref %d\n", iaxc_set_audio_prefs(IAXC_AUDIO_PREF_RECV_REMOTE_RAW | IAXC_AUDIO_PREF_RECV_LOCAL_RAW));
    printf("get audio pref %d\n", iaxc_get_audio_prefs());

    printf("start thread %d\n", iaxc_start_processing_thread());

    int id = -1;
    printf("register %d\n", id = iaxc_register("6003", "1923", "192.168.64.1"));

    int callNo = -1;
    printf("call %d\n", callNo = iaxc_call("6003:1923@192.168.64.1/6001"));

    printf("unquelch: %d\n", iaxc_unquelch(callNo));

    pause();

    printf("finish\n");
    printf("%d\n", iaxc_unregister(id));
    printf("%d\n", iaxc_stop_processing_thread());
    iaxc_shutdown();

    return 0;
}

3
为什么这个问题被踩了? - Folkert van Heusden
1个回答

2
请查看iaxclient_lib.c了解逻辑工作方式。要钩取或替换输入/输出,可以更改函数iaxci_do_audio_callback中的memcpy(e.ev.audio.data, data, size);,其中设置了缓冲区。还要查看service_audio,以了解如何替换发送到远程位置的缓冲区/流(例如want_send_audio和want_local_audio)。您还可以在portaudio中创建虚拟输入/输出设备,以使用缓冲区处理音频,iaxclient将使用这些设备。

要获得更具体的示例,请查看simplecall源代码中的主要方法,以获得良好的开端。但是,源代码太长了,无法复制和粘贴,对此我们表示抱歉。


我在他们当前的svn-trunk中进行了一些黑客攻击,并提出了这个补丁:http://vanheusden.com/iaxclient.diff.gz。有了它,通过缓冲区进行双向音频*有点*可行:有点是因为声音质量非常差。它在各个地方都会卡顿。 - Folkert van Heusden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接