Exemplo n.º 1
0
void* rakVoiceThread( void* arguments )
#endif
{
    SpeexBits bits;
    char output[ 2000 ];
    int outputLength;
    unsigned char typeID;
    PlayerID id;
    BitStream b;
    int availableChunks;
    int MTU;
    int numberOfChunksPerSend;
    int i;
    unsigned long lastSendTime;
    CoderStateWithPlayerIDMapStruct *cswpims;
    lastSendTime = RakNet::GetTime();
    PlayerID target;

    RakVoice *rakVoice = ( RakVoice* ) arguments;

    numberOfChunksPerSend = rakVoice->blockSize / rakVoice->frame_size;

    speex_bits_init( &bits );

    MTU = rakVoice->peer->GetMTUSize();

    while ( rakVoice->init )
    {
        if ( rakVoice->writeCursor >= rakVoice->readCursor )
            availableChunks = rakVoice->writeCursor - rakVoice->readCursor;
        else
            availableChunks = RAK_VOICE_INPUT_LIST_BUFFER_SIZE - rakVoice->readCursor + rakVoice->writeCursor;

        while ( availableChunks >= numberOfChunksPerSend )
        {
            // Get a bit of a buffer before we start sending so we don't "grind" the data and get popping as data continually arrives and runs out

            if ( RakNet::GetTime() - lastSendTime > 1000 && availableChunks < numberOfChunksPerSend * 3 )
                break;

            // Grab data at the read cursor and encode it
            speex_bits_reset( &bits );

            target = rakVoice->targetedSendRecipient[ rakVoice->readCursor ];

            cswpims = rakVoice->GetCoderFromPlayerID( rakVoice->sampleRate, target, false );

            for ( i = 0; i < numberOfChunksPerSend; i++ )
            {
                // For each frame, call speex_encode
                speex_encode( cswpims->encoderState, rakVoice->inputList[ rakVoice->readCursor ], &bits );
                rakVoice->readCursor = ( rakVoice->readCursor + 1 ) % RAK_VOICE_INPUT_LIST_BUFFER_SIZE;
            }

            availableChunks -= numberOfChunksPerSend;

            // Write the encoded bitstream
            outputLength = speex_bits_write( ( SpeexBits* ) ( &bits ), output, 2000 );
#ifdef _DEBUG

            static bool printOnce = true;

            if ( printOnce == true && outputLength > MTU )
            {
                printf( "Warning - compressed data larger than MTU! This will result in split packets and poor speech.\nYou should use a lower blockSize in the call to Init.\n" );
                printOnce = false;
            }

            else if ( printOnce == true && outputLength < MTU / 4 )
            {
                printf( "Warning - compressed data smaller than 1/4 the MTU.  This is not an efficient use of bandwidth.\nYou might want to use a larger blockSize in the call to Init.\n" );
                printOnce = false;
            }

#endif

            b.Reset();

            typeID = ID_VOICE_PACKET;

            b.Write( typeID );

            b.Write( ( char* ) & target, sizeof( target ) );

            b.Write( rakVoice->bps ); // Write how many bits we are encoding the data with

            b.Write( rakVoice->sampleRate );  // Write the sampling rate

            id = rakVoice->peer->GetInternalID();

            b.Write( ( char* ) & id, sizeof( id ) ); // Write who is sending this packet

            b.Write( cswpims->nextPacketNumber ); // Write what speech packet number this is, so we can compensate for lost packets

            cswpims->nextPacketNumber++;

            b.Write( output, outputLength );


            /*
            // This is for showing memory usage
            printf("PCMQueue=%i PCMQueuePool=%i\ndecoderStateList=%i encoderStateList=%i\n",
            rakVoice->PCMQueue.size(),
            rakVoice->PCMQueuePool.size(),
            rakVoice->decoderStateList.size(),
            rakVoice->encoderStateList.size());
            */

            // THis was for testing as a feedback loop
            //if (target==rakVoice->peer->GetInternalID())
            // rakVoice->DecodeAndQueueSoundPacket((char*)b.GetData(), b.GetNumberOfBytesUsed());
            //else
            rakVoice->peer->Send( &b, HIGH_PRIORITY, RELIABLE_SEQUENCED, 0, target, false );

            lastSendTime = RakNet::GetTime();
        }

        // Send out a packet aggreggate roughly every x ms
#ifdef _WIN32
        Sleep( 30 );

#else

        usleep( 30 * 1000 );

#endif

    }

    speex_bits_destroy( &bits );
    return 0;
}