1

PC (C++ アプリケーション、FMOD-API を使用してオーディオ データをデコードし、UDP ソケット経由で送信) から Android デバイスにオーディオ ストリームを送信したいと考えています。通信はすでに機能しており、Android で「サウンド」(100 ミリ秒のサウンドに続いて 900 ミリ秒の沈黙が交互に続く) を聞くことができます。

音が途切れる理由はわかりません。PC では、同じオーディオ ストリームが高品質で正常に再生されます。問題はAndroidにあると思います..

コードは次のとおりです。

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++ アプリケーションの設定と比較されます。

もう 1 つのステップは、受信したソケット データを一時的な「byte[]」変数に事前にバッファリングし、バッファのサイズ「iAudioBufSize」に達したときにそれを AudioTrack オブジェクトに書き込むことでした。これは役に立ちませんでした。

何かアイデアはありますか?ありがとう

[編集] C++ アプリケーションのコード、FMOD API の例のサンプル「manualdecode」を使用:

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);
}
4

1 に答える 1

0

私はこの問題をやった。混乱は、ラグを作成するのに多くの時間を費やしたログファイルのエントリでした:(

これで、Android クライアントでストリーミングされた音楽を聞くことができます。しかし、まだいくつかの遅れがあります。私は、ソケットと 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);
}

私もさまざまな睡眠のタイミングを試しました。

于 2013-06-06T16:43:34.553 に答える