// // amrFileCodec.cpp // amrDemoForiOS // // Created by Tang Xiaoping on 9/27/11. // Copyright 2011 test. All rights reserved. // #include "amrFileCodec.h" static int amrEncodeMode[] = {4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200}; // Skip the WAVE header to PCM audio data static void SkipToPCMAudioData(FILE* fpwave) { EM_RIFFHEADER riff; EM_FMTBLOCK fmt; EM_XCHUNKHEADER chunk; EM_WAVEFORMATX wfx; int bDataBlock = 0; // 1. Read the RIFF header fread(&riff, 1, sizeof(EM_RIFFHEADER), fpwave); // 2. Read the FMT chunk - if fmt.nFmtSize>16, read the remaining MATX fread(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); if ( chunk.nChunkSize>16 ) { fread(&wfx, 1, sizeof(EM_WAVEFORMATX), fpwave); } else { memcpy(fmt.chFmtID, chunk.chChunkID, 4); fmt.nFmtSize = chunk.nChunkSize; fread(&fmt.wf, 1, sizeof(EM_WAVEFORMAT), fpwave); } // 3.Switch to the data block while(!bDataBlock) { fread(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); if ( !memcmp(chunk.chChunkID, "data", 4) ) { bDataBlock = 1; break; } fseek(fpwave, chunk.nChunkSize, SEEK_CUR); } } // Read PCM frame from wave file // Return 0 for error, otherwise return a positive number of the size of frame static size_t ReadPCMFrame(short speech[], FILE* fpwave, int nChannels, int nBitsPerSample) { size_t nRead = 0; int x = 0, y=0; // unsigned short ush1=0, ush2=0, ush=0; // Original PCM autio frame data unsigned char pcmFrame_8b1[PCM_FRAME_SIZE]; unsigned char pcmFrame_8b2[PCM_FRAME_SIZE<<1]; unsigned short pcmFrame_16b1[PCM_FRAME_SIZE]; unsigned short pcmFrame_16b2[PCM_FRAME_SIZE<<1]; if (nBitsPerSample==8 && nChannels==1) { nRead = fread(pcmFrame_8b1, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave); for(x=0; x> 1; //speech[y] = (short)((short)ush << 7); } } else if (nBitsPerSample==16 && nChannels==1) { nRead = fread(pcmFrame_16b1, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave); for(x=0; x> 1; } } // Return 0 unless read a complete PCM frame if (nRead 8 bits // 16 --> 16 bits int EM_EncodeWAVEFileToAMRFile(const char* pchWAVEFilename, const char* pchAMRFileName, int nChannels, int nBitsPerSample) { FILE* fpwave; FILE* fpamr; /* input speech vector */ short speech[160]; /* counters */ int byte_counter, frames = 0; size_t bytes = 0; /* pointer to encoder state structure */ void *enstate; /* requested mode */ enum Mode req_mode = MR122; int dtx = 0; /* bitstream filetype */ unsigned char amrFrame[MAX_AMR_FRAME_SIZE]; fpwave = fopen(pchWAVEFilename, "rb"); if (fpwave == NULL) { return 0; } // Initialize the amr file fpamr = fopen(pchAMRFileName, "wb"); if (fpamr == NULL) { fclose(fpwave); return 0; } /* write magic number to indicate single channel AMR file storage format */ bytes = fwrite(AMR_MAGIC_NUMBER, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr); /* skip to pcm audio data*/ SkipToPCMAudioData(fpwave); enstate = Encoder_Interface_init(dtx); while(1) { // read one pcm frame if (!ReadPCMFrame(speech, fpwave, nChannels, nBitsPerSample)) break; frames++; /* call encoder */ byte_counter = Encoder_Interface_Encode(enstate, req_mode, speech, amrFrame, 0); bytes += byte_counter; fwrite(amrFrame, sizeof (unsigned char), byte_counter, fpamr ); } Encoder_Interface_exit(enstate); fclose(fpamr); fclose(fpwave); return frames; } #pragma mark - Decode //decode static void WriteWAVEFileHeader(FILE* fpwave, int nFrame) { char tag[10] = ""; // 1. RIFF header EM_RIFFHEADER riff; strcpy(tag, "RIFF"); memcpy(riff.chRiffID, tag, 4); riff.nRiffSize = 4 // WAVE + sizeof(EM_XCHUNKHEADER) // fmt + sizeof(EM_WAVEFORMATX) // EM_WAVEFORMATX + sizeof(EM_XCHUNKHEADER) // DATA + nFrame*160*sizeof(short); // strcpy(tag, "WAVE"); memcpy(riff.chRiffFormat, tag, 4); fwrite(&riff, 1, sizeof(EM_RIFFHEADER), fpwave); // 2. FMT chunk EM_XCHUNKHEADER chunk; EM_WAVEFORMATX wfx; strcpy(tag, "fmt "); memcpy(chunk.chChunkID, tag, 4); chunk.nChunkSize = sizeof(EM_WAVEFORMATX); fwrite(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); memset(&wfx, 0, sizeof(EM_WAVEFORMATX)); wfx.nFormatTag = 1; wfx.nChannels = 1; // Single channel wfx.nSamplesPerSec = 8000; // 8khz wfx.nAvgBytesPerSec = 16000; wfx.nBlockAlign = 2; wfx.nBitsPerSample = 16; fwrite(&wfx, 1, sizeof(EM_WAVEFORMATX), fpwave); // 3. Write data chunk strcpy(tag, "data"); memcpy(chunk.chChunkID, tag, 4); chunk.nChunkSize = nFrame*160*sizeof(short); fwrite(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); } static const int myround(const double x) { return((int)(x+0.5)); } // Calculate the AMR frame size with the frame header static int caclAMRFrameSize(unsigned char frameHeader) { int mode; int temp1 = 0; int temp2 = 0; int frameSize; temp1 = frameHeader; // Get AMR Encode Mode with the 3 - 6 digit of frame header temp1 &= 0x78; // 0111-1000 temp1 >>= 3; mode = amrEncodeMode[temp1]; // Calculate the arm auodio framze size // Theory: one frame is 20 mili seconds, then one second is 50 frames of audio data temp2 = myround((double)(((double)mode / (double)AMR_FRAME_COUNT_PER_SECOND) / (double)8)); frameSize = myround((double)temp2 + 0.5); return frameSize; } // Read the first AMR frame - (Reference frame) // return 0 for error and 1 for success static int ReadAMRFrameFirst(FILE* fpamr, unsigned char frameBuffer[], int* stdFrameSize, unsigned char* stdFrameHeader) { //memset(frameBuffer, 0, sizeof(frameBuffer)); // Read the frame header fread(stdFrameHeader, 1, sizeof(unsigned char), fpamr); if (feof(fpamr)) return 0; // Calculate the frame size with frame header *stdFrameSize = caclAMRFrameSize(*stdFrameHeader); // Read the first frame frameBuffer[0] = *stdFrameHeader; fread(&(frameBuffer[1]), 1, (*stdFrameSize-1)*sizeof(unsigned char), fpamr); if (feof(fpamr)) return 0; return 1; } static int ReadAMRFrame(FILE* fpamr, unsigned char frameBuffer[], int stdFrameSize, unsigned char stdFrameHeader) { size_t bytes = 0; unsigned char frameHeader; // 帧头 //memset(frameBuffer, 0, sizeof(frameBuffer)); // Read the frame header // If it is a bad frame(not a standard frame),continue for the next byte while(1) { bytes = fread(&frameHeader, 1, sizeof(unsigned char), fpamr); if (feof(fpamr)) return 0; if (frameHeader == stdFrameHeader) break; } // Audio data for the frame (frame header has beeen read) frameBuffer[0] = frameHeader; bytes = fread(&(frameBuffer[1]), 1, (stdFrameSize-1)*sizeof(unsigned char), fpamr); if (feof(fpamr)) return 0; return 1; } // Decode AMR to WAVE file int EM_DecodeAMRFileToWAVEFile(const char* pchAMRFileName, const char* pchWAVEFilename) { FILE* fpamr = NULL; FILE* fpwave = NULL; char magic[8]; void * destate; int nFrameCount = 0; int stdFrameSize; unsigned char stdFrameHeader; unsigned char amrFrame[MAX_AMR_FRAME_SIZE]; short pcmFrame[PCM_FRAME_SIZE]; fpamr = fopen(pchAMRFileName, "rb"); if ( fpamr==NULL ) return 0; // Check the amr file header fread(magic, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr); if (strncmp(magic, AMR_MAGIC_NUMBER, strlen(AMR_MAGIC_NUMBER))) { fclose(fpamr); return 0; } // Initialize the wave file // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // NSString *documentPath = [paths objectAtIndex:0]; // NSString *docFilePath = [documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%s", pchWAVEFilename]]; // NSLog(@"documentPath=%@", documentPath); // // fpwave = fopen([docFilePath cStringUsingEncoding:NSASCIIStringEncoding], "wb"); fpwave = fopen(pchWAVEFilename,"wb"); WriteWAVEFileHeader(fpwave, nFrameCount); /* init decoder */ destate = Decoder_Interface_init(); // Read the first frame as a reference frame memset(amrFrame, 0, MAX_AMR_FRAME_SIZE); memset(pcmFrame, 0, PCM_FRAME_SIZE); ReadAMRFrameFirst(fpamr, amrFrame, &stdFrameSize, &stdFrameHeader); // Decode an AMR audio frame to PCM data Decoder_Interface_Decode(destate, amrFrame, pcmFrame, 0); nFrameCount++; fwrite(pcmFrame, sizeof(short), PCM_FRAME_SIZE, fpwave); // Decode every frame of AMR and write to WAVE file while(1) { memset(amrFrame, 0, MAX_AMR_FRAME_SIZE); memset(pcmFrame, 0, PCM_FRAME_SIZE); if (!ReadAMRFrame(fpamr, amrFrame, stdFrameSize, stdFrameHeader)) break; // Decode the AMR audio frame to PCM data Decoder_Interface_Decode(destate, amrFrame, pcmFrame, 0); nFrameCount++; fwrite(pcmFrame, sizeof(short), PCM_FRAME_SIZE, fpwave); } //NSLog(@"frame = %d", nFrameCount); Decoder_Interface_exit(destate); fclose(fpwave); // Re-swrite the wave file header // fpwave = fopen([docFilePath cStringUsingEncoding:NSASCIIStringEncoding], "r+"); fpwave = fopen(pchWAVEFilename, "r+"); WriteWAVEFileHeader(fpwave, nFrameCount); fclose(fpwave); return nFrameCount; } int isMP3File(const char *filePath){ FILE* fpamr = NULL; char magic[8]; fpamr = fopen(filePath, "rb"); if (fpamr==NULL) return 0; int isMp3 = 0; fread(magic, sizeof(char), strlen(MP3_MAGIC_NUMBER), fpamr); if (!strncmp(magic, MP3_MAGIC_NUMBER, strlen(MP3_MAGIC_NUMBER))) { isMp3 = 1; } fclose(fpamr); return isMp3; } int isAMRFile(const char *filePath){ FILE* fpamr = NULL; char magic[8]; fpamr = fopen(filePath, "rb"); if (fpamr==NULL) return 0; int isAmr = 0; fread(magic, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr); if (!strncmp(magic, AMR_MAGIC_NUMBER, strlen(AMR_MAGIC_NUMBER))) { isAmr = 1; } fclose(fpamr); return isAmr; }