Convert PCM to Ulaw
將音檔格式從 pcm 編碼成 ulaw 格式
#include <sys\stat.h>
#include <stdio.h>
#include <malloc.h>
unsigned char Linear2Ulaw(register int linear_sample) ;
int Pcm2Ulaw(const char *, const char*);
int GetFileSize( const char * szFileName );
void AddPcmUlawHdr(FILE* fp , int nFileSize);
void main()
{
Pcm2Ulaw("00057.pcm","00057.wav");
}
//
// This routine converts from linear to ulaw
// Input: Signed 16 bit linear sample
// Output: 8 bit ulaw sample
//
unsigned char Linear2Ulaw(register int linear_sample)
{
static int exp_lut[256] = { 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 };
register int sign, exponent, mantissa;
register unsigned char ulaw_byte;
// Convert the linear_sample into sign-magnitude.
if (linear_sample <0) // get magnitude
{
if (linear_sample <-32635)
linear_sample = -32635; // clip magnitude (32635 = 32767-132) and dispose of -32768 problem
linear_sample = -linear_sample;
sign = 0x80; // define sign
}
else
{
if (linear_sample> 32635)
linear_sample = 32635; // clip magnitude (32635 = 32767-132)
sign = 0x00; // define sign
}
// Convert from 15 bit unsigned linear to ulaw.
linear_sample = linear_sample + 132; // bias the magnitude
exponent = exp_lut[linear_sample>> 7]; // exponent = floor(log2((abs(linear_sample)+132)/128))
mantissa = (linear_sample>> (exponent + 3)) & 0x0F;
ulaw_byte = (unsigned char)(sign | (exponent <<4) | mantissa);
ulaw_byte = ~ulaw_byte; // invert bits
// if (ulaw_byte == 0) ulaw_byte = 0x02; // optional CCITT (or MIL-STD?) trap
return ulaw_byte;
}
int Pcm2Ulaw(const char* szInFile , const char* szOutFile)
{
FILE *fin = NULL , *fout = NULL;
int nFileSize = 0;
int nRet = 0;
short *psBuff = NULL;
unsigned char *pucBuff = NULL;
int nSample = 0;
int i = 0;
nFileSize = GetFileSize(szInFile);
if(nFileSize <2)
goto err_out;
if( !(fin = fopen(szInFile,"rb")))
goto err_out;
if( !(fout = fopen(szOutFile,"wb")))
goto err_out;
psBuff = (short*)malloc(nFileSize);
pucBuff = (unsigned char*)malloc(nFileSize/sizeof(short));
if(!psBuff)
goto err_out;
if(!pucBuff)
goto err_out;
fread(psBuff,nFileSize,1,fin);
nSample = nFileSize / sizeof(short);
for(i=0;i<nSample;i++) {
pucBuff[i] = Linear2Ulaw(psBuff[i]);
}
AddPcmUlawHdr(fout, nSample * sizeof(unsigned char));
fwrite(pucBuff,sizeof(unsigned char),nSample,fout);
nRet = 1;
err_out:
if(fin) fclose(fin);
if(fout) fclose(fout);
if(psBuff) free(psBuff);
if(pucBuff) free(pucBuff);
return nRet;
}
int GetFileSize( const char * szFileName )
{
struct stat fileStat;
int err = stat( szFileName, &fileStat );
if (0 != err) return 0;
return fileStat.st_size;
}
void AddPcmUlawHdr(FILE* fp , int nFileSize)
{
int nChunkSize = 0;
int nSubchunk1Size = 18;
short sAudioFormat = 7;
short sChannel = 1;
short sBitsPerSampl = 8;
short sReserve = 0;
int nSampleRate = 8000;
int nByteRate = nSampleRate * sChannel * sBitsPerSampl / 8;
short sBlockAlign = sChannel * sBitsPerSampl / 8;
int nSubchunk2Size = 0;
nSubchunk2Size = nFileSize;
fprintf(fp,"RIFF"); //ChunkID : 4
nChunkSize = nFileSize + 0x24;
fwrite(&nChunkSize,sizeof(int),1,fp); //ChunkSize : 4
fprintf(fp,"WAVE"); //Format : 4
fprintf(fp,"fmt "); //Subchunk1ID : 4
fwrite(&nSubchunk1Size,sizeof(int),1,fp); //Subchunk1Size : 4
fwrite(&sAudioFormat,sizeof(short),1,fp); //AudioFormat : 2
fwrite(&sChannel,sizeof(short),1,fp); //NumChannels : 2
fwrite(&nSampleRate,sizeof(int),1,fp); //SampleRate : 4
fwrite(&nByteRate,sizeof(int),1,fp); //ByteRate : 4
fwrite(&sBlockAlign,sizeof(short),1,fp); //BlockAlign : 2
fwrite(&sBitsPerSampl,sizeof(short),1,fp); //BitsPerSample : 2
fwrite(&sReserve,sizeof(short),1,fp); // Reserved : 2
fprintf(fp,"data"); //Subchunk2ID : 4
fwrite(&nSubchunk2Size,sizeof(int),1,fp); //Subchunk2Size : 4
}