⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 converttog723data.cpp

📁 将指定的16K采样的语音数据文件转换为经G.723编解码后的8K语音数据
💻 CPP
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include ".\HeadH\Head.h"
#include ".\Filter\16to8.h"

extern FSDEF fs;

int InitOutFileHead( dataHEAD filehead, FILE *fp_SpeechOut, unsigned short TotalNumSentence);
int Codec_G723( char *tmpFileIn, char *Dir_Current );

//把给定输入语音文件中的16k采样语音转换为通过G.723编解码之后的8k采样语音,并写入输出文件
//入口参数:FILE *fp_SpeechIn	输入语音文件的指针
//			FILE *fp_SpeechOut	输出语音文件的指针
//			char *Dir_Current	本程序( SpeechViaG723 )所在的目录
int ConvertToG723Data( FILE *fp_SpeechIn, FILE *fp_SpeechOut, char *Dir_Current )
{
	FILE *fp_in, *fp_out;
	FILE *fp_tmpIn = NULL, *fp_tmpOut = NULL;
//	char		str_tmp[_MAX_PATH];
	long		ltemp;
//	long		i;

	//------------------语音输入文件所需变量-------------------//
	dataHEAD	filehead;//记录文件头信息
	unsigned short		TotalNumSentence;	//语音文件的总句子数
	unsigned short		nSentence;//循环计数用
	long		SentenceLength;//句子长度Bytes
	unsigned long		DataStart;//语音数据在binary输出文件中的起始地址
	short		*VoiceData_Short = NULL;//语音数据

	//------------------语音输出文件所需变量-------------------//
	short		*VoiceData_Filtered = NULL;//滤波后的语音数据
//	short		*VoiceData_AfterG723 = NULL;//G.723 编解码后的语音数据
	long		SentenceLength_Filtered;//滤波后的句子长度Bytes
//	long		SentenceLength_AfterG723;//过 G.723 之后的句子长度Bytes
	long		DataOutStart;//语音数据在binary输出文件中的起始地址

	fp_in = fp_SpeechIn;
	fp_out = fp_SpeechOut;

	//读入语音文件的头
	fread( &filehead, sizeof(dataHEAD), 1,fp_in );

	//-----------------------读出语音文件中一共有多少句话--------------------//
	//在863数据中,第199,200字节并没有标识出该文件中总共有多少句话,
	//但是其索引区后紧接数据区,所以从第一个索引的值就可以推算出总共有多少句话
	fseek( fp_in, 200,SEEK_SET );
	fread( &ltemp, sizeof(long), 1, fp_in );//第一个索引的值
	TotalNumSentence = (short)( (ltemp-200)/(2*sizeof(long)) );//每个索引有8个字节:2个long
	//若不是863数据,还有一种格式是每个文件有 >= 1000 句话的索引区
	//这种情况在198字节应该有句子数
	if( TotalNumSentence >= 1000 )
	{
		fseek( fp_in, 198, SEEK_SET );
		fread( &TotalNumSentence, sizeof(short), 1, fp_in );
	}
	printf( "一共%d句话\n", TotalNumSentence );

	//-------------------------------修改文件头-----------------------------//
	strcpy( filehead.ParameterType,"16to8" );
	filehead.SampleType = 2;//在文件头中定义数据类型(1=char;2=short;3=long;4=float;5=double) 
	
	//写文件头到binary输出文件,并初始化索引区
	InitOutFileHead( filehead, fp_out, TotalNumSentence);

	//一句语音数据滤波之后的位置,初值是数据区的起始位置
	DataOutStart = 200 + TotalNumSentence*sizeof(long)*2;

	//初始化滤波器
	initialfilter();
	
	//按句读入语音,并作处理
	for( nSentence = 0; nSentence < TotalNumSentence; nSentence++){

		printf( "第%d句\b\r", nSentence);

		//从第(nSentence)句话的索引区读出该句话语音数据的首地址(DataStart)及总的字节数(SentenceLength)
		fseek( fp_in, 200+2*sizeof(long)*nSentence, SEEK_SET );
		fread( &DataStart, sizeof(long), 1, fp_in );
		fread( &SentenceLength, sizeof(long), 1, fp_in );

		//分配语音内存
		VoiceData_Short = ( short * ) malloc ( SentenceLength );	
		SentenceLength_Filtered = SentenceLength/2;
		VoiceData_Filtered = ( short * ) malloc ( SentenceLength_Filtered );

		//将第(nSentence)句话的语音数据读入内存VoiceData_Short
		fseek( fp_in, DataStart, SEEK_SET );
		fread( VoiceData_Short, SentenceLength, 1, fp_in );

		//----------------------16k->8k,滤波-----------------------//
		//滤波前对本句所需变量做初始化初始化
		initial_sentence();
		//FIR滤波器函数
		for (long i = 0; i < SentenceLength/2; i++ )
			VoiceData_Short[i]=Filter(VoiceData_Short[i], fs.B,fs.x,numFilter);
		//抽取函数
		for ( i = 0; i < SentenceLength_Filtered/2; i++ )
			downsample_16_to_8_one_sentence( VoiceData_Short, VoiceData_Filtered, &fs.j);

		//将第(nSentence)句滤波后的语音写入输出文件
		//写当前句(第nSentence句)的索引区
		fseek( fp_out, 200+sizeof(long)*2*nSentence, SEEK_SET);
		fwrite( &DataOutStart, sizeof(long), 1, fp_out );//本句开始的位置
		fwrite( &SentenceLength_Filtered, sizeof(long), 1, fp_out );//本句的长度
		//写当前句的语音数据
		fseek( fp_out, 0, SEEK_END);
		fwrite( VoiceData_Filtered, 1, SentenceLength_Filtered, fp_out );//这句话的转换后语音
		DataOutStart += SentenceLength_Filtered;//下一句数据输出的起始位置

/*
		//----------------------G.723编解码--------------------------//
		//产生中间文件,把一句滤波后的语音写入中间文件
		sprintf( str_tmp, "%s\\tmp\\tmpIn.dat", Dir_Current);
		fp_tmpIn = fopen( str_tmp, "wb+" );
		if( fp_tmpIn == NULL ){
			perror("Temp In File open error!\n");
			exit(1);
		}
		fwrite( VoiceData_Filtered, 1, SentenceLength_Filtered, fp_tmpIn );
		fclose( fp_tmpIn );

		Codec_G723( "tmpIn.dat", Dir_Current );
		printf( "第%d句\b\r", nSentence);
		//----------------------codec over--------------------------//

		sprintf( str_tmp, "%s\\tmp\\tmpOut.dat", Dir_Current);
		fp_tmpOut = fopen( str_tmp, "rb" );
		if( fp_tmpOut == NULL ){
			perror("Temp Out File open error!\n");
			exit(1);
		}
		//Compute the file length
		fseek( fp_tmpOut, 0L, SEEK_END ) ;
		SentenceLength_AfterG723 = ftell( fp_tmpOut ) ;
		//从 tmpOut.dat 中编解码后的语音读入,准备写入输出文件里
		fseek( fp_tmpOut, 0L, SEEK_SET );
		VoiceData_AfterG723 = ( short * ) malloc ( SentenceLength_AfterG723 );
		fread( VoiceData_AfterG723, SentenceLength_AfterG723, 1, fp_tmpOut );
		fclose( fp_tmpOut );

		//将第(nSentence)句编解码后的语音写入输出文件
		//写当前句(第nSentence句)的索引区
		fseek( fp_out, 200+sizeof(long)*2*nSentence, SEEK_SET);
		fwrite( &DataOutStart, sizeof(long), 1, fp_out );//本句开始的位置
		fwrite( &SentenceLength_AfterG723, sizeof(long), 1, fp_out );//本句的长度
		//写当前句的语音数据
		fseek( fp_out, 0, SEEK_END);
		fwrite( VoiceData_AfterG723, 1, SentenceLength_AfterG723, fp_out );//这句话的转换后语音
		DataOutStart += SentenceLength_AfterG723;//下一句数据输出的起始位置
*/
		//释放内存
		if( VoiceData_Short != NULL ){
			free( VoiceData_Short );
			VoiceData_Short = NULL;
		}
		if( VoiceData_Filtered != NULL ){
			free( VoiceData_Filtered );
			VoiceData_Filtered = NULL;
		}
/*		if( VoiceData_AfterG723 != NULL ){
			free( VoiceData_AfterG723 );
			VoiceData_AfterG723 = NULL;
		}
*/	}

	return 0;
}

//写文件头到binary输出文件,并初始化索引区
int InitOutFileHead( dataHEAD filehead, FILE *fp_out, unsigned short TotalNumSentence)
{
	long	ltemp = 0, i;
	long	Length_index;//binary输出文件中索引区长度

	if( !fp_out ){
		perror("OutputFile not open!\n");
		exit(1);
	}
	
	//-----------------------写文件头到binary输出文件,并初始化索引区------------------//
	//前196个字节
	fwrite( &filehead, sizeof(dataHEAD), 1, fp_out);
	//第197,198字节放空
	fwrite( &ltemp, sizeof(char), 2, fp_out);
	//第199,200字节写入总共有多少句子
	fwrite( &TotalNumSentence, sizeof(short), 1, fp_out);
	
	//计算binary输出文件中索引区长度
	Length_index = TotalNumSentence*sizeof(long)*2;//bytes
	//计算每句索引的位置(bytes),这里获得初始值

	//对输出文件的句子索引区进行初始化,随便写
	for( i = 0; i < Length_index; i++ )
		fwrite( &ltemp, sizeof(char), 1, fp_out);

	return 0;
}

/*
//G.723编解码
int Codec_G723( char *tmpFileIn, char *Dir_Current )
{
	char cInstruction[500];

	//把编解码命令行写入 cInstruction
	sprintf( cInstruction, "%s\\G723_fixedpoint -b -r53  -v %s\\tmp\\%s %s\\tmp\\tmpOut.dat > .\\tmp\\intermedia", Dir_Current, Dir_Current, tmpFileIn, Dir_Current );
	system( cInstruction );

	return 0;
}
*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -