skype的语音编码方案开源的组件是silk,越来越多的APP采用此方案,差了些资料,找到了对应的解码代码,共享下。
官方的解码示例:
int main( int argc, char* argv[] )
{
unsigned long tottime, starttime;
double filetime;
size_t counter;
SKP_int32 args, totPackets, i, k;
SKP_int16 ret, len, tot_len;
SKP_int16 nBytes;
SKP_uint8 payload[ MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
SKP_uint8 *payloadEnd = NULL, *payloadToDec = NULL;
SKP_uint8 FECpayload[ MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES ], *payloadPtr;
SKP_int16 nBytesFEC;
SKP_int16 nBytesPerPacket[ MAX_LBRR_DELAY + 1 ], totBytes;
SKP_int16 out[ ( ( FRAME_LENGTH_MS * MAX_API_FS_KHZ ) << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
char speechOutFileName[ 150 ], bitInFileName[ 150 ];
FILE *bitInFile, *speechOutFile;
SKP_int32 packetSize_ms=0, API_Fs_Hz = 0;
SKP_int32 decSizeBytes;
void *psDec;
SKP_float loss_prob;
SKP_int32 frames, lost, quiet;
SKP_SILK_SDK_DecControlStruct DecControl;
if( argc < 3 ) {
print_usage( argv );
exit( 0 );
}
/* default settings */
quiet = 0;
loss_prob = 0.0f;
/* get arguments */
args = 1;
strcpy( bitInFileName, argv[ args ] );
args++;
strcpy( speechOutFileName, argv[ args ] );
args++;
while( args < argc ) {
if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-loss" ) == 0 ) {
sscanf( argv[ args + 1 ], "%f", &loss_prob );
args += 2;
} else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-Fs_API" ) == 0 ) {
sscanf( argv[ args + 1 ], "%d", &API_Fs_Hz );
args += 2;
} else if( SKP_STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-quiet" ) == 0 ) {
quiet = 1;
args++;
} else {
printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
print_usage( argv );
exit( 0 );
}
}
if( !quiet ) {
printf("********** Silk Decoder (Fixed Point) v %s ********************\n", SKP_Silk_SDK_get_version());
printf("********** Compiled for %d bit cpu *******************************\n", (int)sizeof(void*) * 8 );
printf( "Input: %s\n", bitInFileName );
printf( "Output: %s\n", speechOutFileName );
}
/* Open files */
bitInFile = fopen( bitInFileName, "rb" );
if( bitInFile == NULL ) {
printf( "Error: could not open input file %s\n", bitInFileName );
exit( 0 );
}
/* Check Silk header */
{
char header_buf[ 50 ];
counter = fread( header_buf, sizeof( char ), strlen( "#!SILK_V3" ), bitInFile );
header_buf[ strlen( "#!SILK_V3" ) ] = '\0'; /* Terminate with a null character */
if( strcmp( header_buf, "#!SILK_V3" ) != 0 ) {
/* Non-equal strings */
printf( "Error: Wrong Header %s\n", header_buf );
exit( 0 );
}
}
speechOutFile = fopen( speechOutFileName, "wb" );
if( speechOutFile == NULL ) {
printf( "Error: could not open output file %s\n", speechOutFileName );
exit( 0 );
}
/* Set the samplingrate that is requested for the output */
if( API_Fs_Hz == 0 ) {
DecControl.API_sampleRate = 24000;
} else {
DecControl.API_sampleRate = API_Fs_Hz;
}
/* Initialize to one frame per packet, for proper concealment before first packet arrives */
DecControl.framesPerPacket = 1;
/* Create decoder */
ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
if( ret ) {
printf( "\nSKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
}
psDec = malloc( decSizeBytes );
/* Reset decoder */
ret = SKP_Silk_SDK_InitDecoder( psDec );
if( ret ) {
printf( "\nSKP_Silk_InitDecoder returned %d", ret );
}
totPackets = 0;
tottime = 0;
payloadEnd = payload;
/* Simulate the jitter buffer holding MAX_FEC_DELAY packets */
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
/* Read payload size */
counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( &nBytes, 1 );
#endif
/* Read payload */
counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );
if( ( SKP_int16 )counter < nBytes ) {
break;
}
nBytesPerPacket[ i ] = nBytes;
payloadEnd += nBytes;
totPackets++;
}
while( 1 ) {
/* Read payload size */
counter = fread( &nBytes, sizeof( SKP_int16 ), 1, bitInFile );
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( &nBytes, 1 );
#endif
if( nBytes < 0 || counter < 1 ) {
break;
}
/* Read payload */
counter = fread( payloadEnd, sizeof( SKP_uint8 ), nBytes, bitInFile );
if( ( SKP_int16 )counter < nBytes ) {
break;
}
/* Simulate losses */
rand_seed = SKP_RAND( rand_seed );
if( ( ( ( float )( ( rand_seed >> 16 ) + ( 1 << 15 ) ) ) / 65535.0f >= ( loss_prob / 100.0f ) ) && ( counter > 0 ) ) {
nBytesPerPacket[ MAX_LBRR_DELAY ] = nBytes;
payloadEnd += nBytes;
} else {
nBytesPerPacket[ MAX_LBRR_DELAY ] = 0;
}
if( nBytesPerPacket[ 0 ] == 0 ) {
/* Indicate lost packet */
lost = 1;
/* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */
payloadPtr = payload;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
if( nBytesPerPacket[ i + 1 ] > 0 ) {
starttime = GetHighResolutionTime();
SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], ( i + 1 ), FECpayload, &nBytesFEC );
tottime += GetHighResolutionTime() - starttime;
if( nBytesFEC > 0 ) {
payloadToDec = FECpayload;
nBytes = nBytesFEC;
lost = 0;
break;
}
}
payloadPtr += nBytesPerPacket[ i + 1 ];
}
} else {
lost = 0;
nBytes = nBytesPerPacket[ 0 ];
payloadToDec = payload;
}
/* Silk decoder */
outPtr = out;
tot_len = 0;
starttime = GetHighResolutionTime();
if( lost == 0 ) {
/* No Loss: Decode all frames in the packet */
frames = 0;
do {
/* Decode 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_SDK_Decode returned %d", ret );
}
frames++;
outPtr += len;
tot_len += len;
if( frames > MAX_INPUT_FRAMES ) {
/* Hack for corrupt stream that could generate too many frames */
outPtr = out;
tot_len = 0;
frames = 0;
}
/* Until last 20 ms frame of packet has been decoded */
} while( DecControl.moreInternalDecoderFrames );
} else {
/* Loss: Decode enough frames to cover one packet duration */
for( i = 0; i < DecControl.framesPerPacket; i++ ) {
/* Generate 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_Decode returned %d", ret );
}
outPtr += len;
tot_len += len;
}
}
packetSize_ms = tot_len / ( DecControl.API_sampleRate / 1000 );
tottime += GetHighResolutionTime() - starttime;
totPackets++;
/* Write output to file */
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( out, tot_len );
#endif
fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );
/* Update buffer */
totBytes = 0;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
totBytes += nBytesPerPacket[ i + 1 ];
}
SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );
payloadEnd -= nBytesPerPacket[ 0 ];
SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );
if( !quiet ) {
fprintf( stderr, "\rPackets decoded: %d", totPackets );
}
}
/* Empty the recieve buffer */
for( k = 0; k < MAX_LBRR_DELAY; k++ ) {
if( nBytesPerPacket[ 0 ] == 0 ) {
/* Indicate lost packet */
lost = 1;
/* Packet loss. Search after FEC in next packets. Should be done in the jitter buffer */
payloadPtr = payload;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
if( nBytesPerPacket[ i + 1 ] > 0 ) {
starttime = GetHighResolutionTime();
SKP_Silk_SDK_search_for_LBRR( payloadPtr, nBytesPerPacket[ i + 1 ], ( i + 1 ), FECpayload, &nBytesFEC );
tottime += GetHighResolutionTime() - starttime;
if( nBytesFEC > 0 ) {
payloadToDec = FECpayload;
nBytes = nBytesFEC;
lost = 0;
break;
}
}
payloadPtr += nBytesPerPacket[ i + 1 ];
}
} else {
lost = 0;
nBytes = nBytesPerPacket[ 0 ];
payloadToDec = payload;
}
/* Silk decoder */
outPtr = out;
tot_len = 0;
starttime = GetHighResolutionTime();
if( lost == 0 ) {
/* No loss: Decode all frames in the packet */
frames = 0;
do {
/* Decode 20 ms */
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_SDK_Decode returned %d", ret );
}
frames++;
outPtr += len;
tot_len += len;
if( frames > MAX_INPUT_FRAMES ) {
/* Hack for corrupt stream that could generate too many frames */
outPtr = out;
tot_len = 0;
frames = 0;
}
/* Until last 20 ms frame of packet has been decoded */
} while( DecControl.moreInternalDecoderFrames );
} else {
/* Loss: Decode enough frames to cover one packet duration */
/* Generate 20 ms */
for( i = 0; i < DecControl.framesPerPacket; i++ ) {
ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 1, payloadToDec, nBytes, outPtr, &len );
if( ret ) {
printf( "\nSKP_Silk_Decode returned %d", ret );
}
outPtr += len;
tot_len += len;
}
}
packetSize_ms = tot_len / ( DecControl.API_sampleRate / 1000 );
tottime += GetHighResolutionTime() - starttime;
totPackets++;
/* Write output to file */
#ifdef _SYSTEM_IS_BIG_ENDIAN
swap_endian( out, tot_len );
#endif
fwrite( out, sizeof( SKP_int16 ), tot_len, speechOutFile );
/* Update Buffer */
totBytes = 0;
for( i = 0; i < MAX_LBRR_DELAY; i++ ) {
totBytes += nBytesPerPacket[ i + 1 ];
}
SKP_memmove( payload, &payload[ nBytesPerPacket[ 0 ] ], totBytes * sizeof( SKP_uint8 ) );
payloadEnd -= nBytesPerPacket[ 0 ];
SKP_memmove( nBytesPerPacket, &nBytesPerPacket[ 1 ], MAX_LBRR_DELAY * sizeof( SKP_int16 ) );
if( !quiet ) {
fprintf( stderr, "\rPackets decoded: %d", totPackets );
}
}
if( !quiet ) {
printf( "\nDecoding Finished \n" );
}
/* Free decoder */
free( psDec );
/* Close files */
fclose( speechOutFile );
fclose( bitInFile );
filetime = totPackets * 1e-3 * packetSize_ms;
if( !quiet ) {
printf("\nFile length: %.3f s", filetime);
printf("\nTime for decoding: %.3f s (%.3f%% of realtime)", 1e-6 * tottime, 1e-4 * tottime / filetime);
printf("\n\n");
} else {
/* print time and % of realtime */
printf( "%.3f %.3f %d\n", 1e-6 * tottime, 1e-4 * tottime / filetime, totPackets );
}
return 0;
}
修修改改调整下即可使用,测试通过。
至于里面包含的头和lib可以直接google源码下载直接编译出来即可,太多了,比如https://github.com/Voxer/silk-arm-ios ,里面附带了VS工程,可以直接编译。
2015/1/29 | Tags:语音解码,VC,silk | C/C++代码 | 查看评论(4)