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



我想发送一个音频流从PC (c++应用程序,使用FMOD-API解码音频数据,并通过UDP套接字发送)到android设备。通信已经工作,我可以听到"声音"(100ms的声音,然后是900ms的沉默,交替)在android上。

我不知道为什么声音是断断续续的-在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());
}

我确定正确设置了AudioTrack对象,设置与我在c++应用程序中的设置相比较。

另一个步骤是在临时'byte[]'变量中预缓冲接收到的套接字数据,并在达到'iAudioBufSize'缓冲区的大小时将其写入AudioTrack-object。

有什么想法吗?由于

[编辑]c++应用程序代码,使用示例"manualdecode"的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);
}

我做过这个问题。这个mess是日志文件中的一个条目,它花费了大量的时间来创建延迟:(

现在我可以听到流媒体音乐在我的安卓客户端。但仍有一些滞后。我已经尝试了很多套接字和AudioTrack缓冲区的值。我比较了发送和接收的字节量:在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);
}

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

相关内容

  • 没有找到相关文章

最新更新