Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 播放通过UDP套接字接收的流时出现口吃播放_Android_Sockets_Stream_Udp_Audiotrack - Fatal编程技术网

Android 播放通过UDP套接字接收的流时出现口吃播放

Android 播放通过UDP套接字接收的流时出现口吃播放,android,sockets,stream,udp,audiotrack,Android,Sockets,Stream,Udp,Audiotrack,我想从PC(C++应用程序,使用FMOD-API解码音频数据并通过UDP套接字发送)向android设备发送音频流。通讯已经开始,我可以在android上听到“声音”(100毫秒的声音,接着是900毫秒的静音,交替) 我不知道为什么声音会断断续续——在PC上,同样的音频流播放质量很好。我认为问题出在安卓系统上 代码如下: DatagramSocket sock = new DatagramSocket(12345); byte []bSockBuffer = new by

我想从PC(C++应用程序,使用FMOD-API解码音频数据并通过UDP套接字发送)向android设备发送音频流。通讯已经开始,我可以在android上听到“声音”(100毫秒的声音,接着是900毫秒的静音,交替)

我不知道为什么声音会断断续续——在PC上,同样的音频流播放质量很好。我认为问题出在安卓系统上

代码如下:

DatagramSocket  sock = new DatagramSocket(12345);
byte            []bSockBuffer = new byte[1024];
byte            []bRecvBufTmp;
int             iAudioBufSize, iCurAudioBufPos = 0;

sock.setReceiveBufferSize(bSockBuffer.length);

// Audio Stream initialisieren:
iAudioBufSize       = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);

AudioTrack track    = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO,
                                    AudioFormat.ENCODING_PCM_16BIT, iAudioBufSize, AudioTrack.MODE_STREAM);

track.play();

while (true)
{
    DatagramPacket pack = new DatagramPacket(bSockBuffer, bSockBuffer.length);

    // Paket empfangen:
    sock.receive(pack);

    track.write(pack.getData(), 0, pack.getLength());
}
我确信正确设置“AudioTrar”对象,设置与C++应用程序中的设置相比较。

另一个步骤是在临时“byte[]”变量中预缓冲接收到的套接字数据,并在达到缓冲区“iAudioBufSize”的大小时将其写入AudioTrack对象。 这没有帮助

有什么想法吗? 谢谢

[编辑] C++应用程序代码,使用FMOD API示例的“手工解码”示例:

FMOD_RESULT F_CALLBACK pcmreadcallback(FMOD_SOUND *sound, void *data, unsigned int datalen)
{
    CCtrlSocket     *cClientTmp = /* Obtaining target client sock here */;
    FMOD_RESULT     result;
    unsigned int    read, uSentTmp, uSizeTmp;

    EnterCriticalSection(&decodecrit);

    if (!decodesound)
        return (FMOD_ERR_FILE_EOF);

    result = decodesound->readData(data, datalen, &read);

    if (result == FMOD_ERR_FILE_EOF)
    {
        // Handle looping:
        decodesound->seekData(0);

        datalen -= read;

        result = decodesound->readData((char*) data + read, datalen, &read);
    }

    // Split package in multiple parts:
    uSentTmp = 0;

    do
    {
        uSizeTmp = (read - uSentTmp);

        if (uSizeTmp > 1024)
            uSizeTmp = 1024;

        uSentTmp += cClientTmp->SendAudioData((char*) data + uSentTmp, uSizeTmp);

    } while (uSentTmp < read);

    LeaveCriticalSection(&decodecrit);

    return (FMOD_OK);
}
FMOD_结果F_回调pcmreadcallback(FMOD_SOUND*SOUND,void*data,unsigned int datalen)
{
CCtrlSocket*cClientTmp=/*在此处获取目标客户端sock*/;
FMOD_结果;
无符号整型读取,uSentTmp,uSizeTmp;
EnterCriticalSection(&decodecrit);
如果(!解码声音)
返回(FMOD\u ERR\u FILE\u EOF);
结果=解码声音->读取数据(数据、数据列和读取);
如果(结果==FMOD\U ERR\U文件\U EOF)
{
//句柄循环:
解码声音->搜索数据(0);
datalen-=读取;
结果=解码声音->读取数据((字符*)数据+读取、数据长度和读取);
}
//将包装拆分为多个部分:
uSentTmp=0;
做
{
uSizeTmp=(read-uSentTmp);
如果(uSizeTmp>1024)
uSizeTmp=1024;
uSentTmp+=cClientTmp->SendAudioData((char*)数据+uSentTmp,uSizeTmp);
}while(uSentTmp
我已经解决了这个问题。 混乱是日志文件中的一个条目,花费了大量时间造成了延迟:(

现在我可以在我的android客户端上听到流式音乐。但是仍然有一些滞后。我已经试验了很多套接字和音轨缓冲区的值。 我比较了发送和接收字节的数量:在20秒内,发送9170000字节的数据会导致在android设备上接收8120000字节。起初,流播放速度很快,持续3秒(这意味着缓冲区已满?)。30秒后,流延迟(这意味着缓冲区已空?)。 总体而言,音乐质量非常好,但始终有嘶嘶声(这表示插座包丢失?)

我的“PlaybackStart()”函数已更改-我不再使用PCM读取回调:

FMOD_RESULT CAudioStream::PlaybackStart()
{
    CCtrlSocket     *cClientTmp;
    unsigned int    read, uSentTmp, uSizeTmp;
    FMOD_RESULT result;

    result = system->createStream("C:\\test.mp3", FMOD_OPENONLY | FMOD_ACCURATETIME, 0, &sound);
    if(result != FMOD_OK)
        return (result);

    int iChannels, iBits;
    FMOD_SOUND_FORMAT fFormat;
    FMOD_SOUND_TYPE fType;

    result = sound->getFormat(&fType, &fFormat, &iChannels, &iBits);
    if(result != FMOD_OK)
        return (result);



    void *data;
    unsigned int length = 0;
    int iSampleSec          = 1;                // Playtime
    int iSampleSize         = (44100 * 2 * sizeof(signed short) * iSampleSec);
    int iSleep              = 6;                // Sleep after sending a package
    DWORD   dSleepTotal;


    result = sound->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
    if(result != FMOD_OK)
        return (result);

    data = malloc(iSampleSize);
    if (!data)
        return (FMOD_RESULT_FORCEINT);

    cClientTmp = (CCtrlSocket*) CCtrlSocket::cServerSock.GetClientSock(CCtrlSocket::cServerSock.GetClientSockCount() - 1);

    do
    {
        result = sound->readData((char*) data, iSampleSize, &read);

        if ((result != FMOD_OK) && (result != FMOD_ERR_FILE_EOF))
            ASSERT(FALSE);

        else if (read > 0)
        {
            dSleepTotal = 0;

            for (int i = 0; i < read; i += NET_SVR_AUDIO_BUFFER)
            {
                // MIN_VAL_LIMITED      ((MIN_VAL(VAL1, VAL2) <= LIMIT) ? LIMIT : MIN_VAL(VAL1, VAL2))
                cClientTmp->SendAudioData((char*) data + i, MIN_VAL_LIMITED(NET_SVR_AUDIO_BUFFER, (read - i), 0));

                // Sleep after sending every package:
                Sleep(iSleep);
                dSleepTotal += iSleep;
            }

            if (dSleepTotal < (iSampleSec * 1000))
            {
                dSleepTotal = (iSampleSec * 1000) - dSleepTotal;

                // Sleep after sending every second playtime:
                Sleep(dSleepTotal);
            }
        }

    } while (read > 0);



    result = sound->release();
    if(result != FMOD_OK)
        return (result);

    result = system->close();
    if(result != FMOD_OK)
        return (result);

    result = system->release();
    if(result != FMOD_OK)
        return (result);

    return (result);
}
FMOD_结果CAudioStream::PlaybackStart()
{
CCtrlSocket*cClientTmp;
无符号整型读取,uSentTmp,uSizeTmp;
FMOD_结果;
结果=系统->createStream(“C:\\test.mp3”,FMOD_OPENONLY | FMOD_accurrateTime,0,&sound);
如果(结果!=FMOD\U正常)
返回(结果);
国际iChannels,iBits;
FMOD_声音_格式格式格式;
FMOD_声音_类型F类型;
结果=声音->获取格式(&fType,&fFormat,&iChannels,&iBits);
如果(结果!=FMOD\U正常)
返回(结果);
作废*数据;
无符号整数长度=0;
int iSampleSec=1;//播放时间
int iSampleSize=(44100*2*sizeof(签名短)*iSampleSec);
int iSleep=6;//发送包后休眠
德沃德·德雷普托尔;
结果=声音->获取长度(&length,FMOD\u TIMEUNIT\u PCMBYTES);
如果(结果!=FMOD\U正常)
返回(结果);
数据=malloc(iSampleSize);
如果(!数据)
返回(FMOD_结果_强制输入);
cClientTmp=(CCtrlSocket*)CCtrlSocket::cServerSock.GetClientSock(CCtrlSocket::cServerSock.GetClientSockCount()-1);
做
{
结果=声音->读取数据((char*)数据,iSampleSize,&read);
如果((结果!=FMOD\U OK)&&(结果!=FMOD\U ERR\U文件\U EOF))
断言(假);
否则如果(读取>0)
{
dSleepTotal=0;
对于(int i=0;i0);
结果=声音->释放();
如果(结果!=FMOD\U正常)
返回(结果);
结果=系统->关闭();
如果(结果!=FMOD\U正常)
返回(结果);
结果=系统->发布();
如果(结果!=FMOD\U正常)
返回(结果);
返回(结果);
}

我也尝试过不同的睡眠时间。

你知道UDP数据报可能比1024字节大,对吗?实际的包大小是多少?我已经把我的C++应用程序中的每个发送包都切成1024字节。我还比较了发送和接收的大小。它应该适合。你应该尝试改变缓冲区大小。udioTrack player将当前值乘以2或3,然后检查是否有更改我已经尝试过大小..更改AudioTrack缓冲区的大小会导致更改静默的持续时间。我还尝试了一个线程。sleep([各种计时]);after track.write();-更改静默的持续时间…解决了问题!UDP丢失了一些包(那是嘶嘶声)而口吃来自未分类的传入包。在TCP/IP上一切都很好!