├── EMVoiceConverter.h ├── EMVoiceConverter.mm ├── README.md ├── amrwapper ├── amrFileCodec.h ├── amrFileCodec.mm ├── wav.h └── wav.mm ├── opencore-amrnb ├── interf_dec.h ├── interf_enc.h └── libopencore-amrnb.a ├── opencore-amrwb ├── dec_if.h ├── if_rom.h └── libopencore-amrwb.a └── sayhi.txt /EMVoiceConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // VoiceConverter.h 3 | // Jeans 4 | // 5 | // Created by Jeans Huang on 12-7-22. 6 | // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "amrFileCodec.h" 11 | 12 | @interface EMVoiceConverter : NSObject 13 | 14 | // WAVE音频采样频率是8khz 15 | // 音频样本单元数 = 8000*0.02 = 160 (由采样频率决定) 16 | // 声道数 1 : 160 17 | // 2 : 160*2 = 320 18 | // bps决定样本(sample)大小 19 | // bps = 8 --> 8位 unsigned char 20 | // 16 --> 16位 unsigned short 21 | int EM_EncodeWAVEFileToAMRFile(const char* pchWAVEFilename, const char* pchAMRFileName, int nChannels, int nBitsPerSample); 22 | 23 | // 将AMR文件解码成WAVE文件 24 | int EM_DecodeAMRFileToWAVEFile(const char* pchAMRFileName, const char* pchWAVEFilename); 25 | 26 | //是否是 MP3文件 27 | int isMP3File(const char *filePath); 28 | 29 | //是否是AMR 文件 30 | int isAMRFile(const char *filePath); 31 | 32 | 33 | + (int)isAMRFile:(NSString *)filePath; 34 | 35 | + (int)isMP3File:(NSString *)filePath; 36 | 37 | + (int)amrToWav:(NSString*)_amrPath wavSavePath:(NSString*)_savePath; 38 | 39 | + (int)wavToAmr:(NSString*)_wavPath amrSavePath:(NSString*)_savePath; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /EMVoiceConverter.mm: -------------------------------------------------------------------------------- 1 | // 2 | // VoiceConverter.m 3 | // Jeans 4 | // 5 | // Created by Jeans Huang on 12-7-22. 6 | // Copyright (c) 2012年 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "EMVoiceConverter.h" 10 | #import "wav.h" 11 | #import "interf_dec.h" 12 | #import "dec_if.h" 13 | #import "interf_enc.h" 14 | 15 | 16 | @implementation EMVoiceConverter 17 | 18 | + (int)isMP3File:(NSString *)filePath{ 19 | const char *_filePath = [filePath cStringUsingEncoding:NSASCIIStringEncoding]; 20 | return isMP3File(_filePath); 21 | } 22 | 23 | + (int)isAMRFile:(NSString *)filePath{ 24 | const char *_filePath = [filePath cStringUsingEncoding:NSASCIIStringEncoding]; 25 | return isAMRFile(_filePath); 26 | } 27 | 28 | + (int)amrToWav:(NSString*)_amrPath wavSavePath:(NSString*)_savePath{ 29 | 30 | if (EM_DecodeAMRFileToWAVEFile([_amrPath cStringUsingEncoding:NSASCIIStringEncoding], [_savePath cStringUsingEncoding:NSASCIIStringEncoding])) 31 | return 0; // success 32 | 33 | return 1; // failed 34 | } 35 | 36 | + (int)wavToAmr:(NSString*)_wavPath amrSavePath:(NSString*)_savePath{ 37 | 38 | if (EM_EncodeWAVEFileToAMRFile([_wavPath cStringUsingEncoding:NSASCIIStringEncoding], [_savePath cStringUsingEncoding:NSASCIIStringEncoding], 1, 16)) 39 | return 0; // success 40 | 41 | return 1; // failed 42 | } 43 | 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VoiceConvert 2 | iOS 录音文件格式转换类 3 | 4 | 这是一个 转换音频文件的三方库,同时也可以录音和播放 音频文件。非常方便。 5 | 6 | 直接导入程序中,引入头文件直接使用。 7 | -------------------------------------------------------------------------------- /amrwapper/amrFileCodec.h: -------------------------------------------------------------------------------- 1 | // 2 | // amrFileCodec.h 3 | // amrDemoForiOS 4 | // 5 | // Created by Tang Xiaoping on 9/27/11. 6 | // Copyright 2011 test. All rights reserved. 7 | // 8 | #ifndef amrFileCodec_h 9 | #define amrFileCodec_h 10 | #include 11 | #include 12 | #include 13 | #include "interf_dec.h" 14 | #include "interf_enc.h" 15 | 16 | #define AMR_MAGIC_NUMBER "#!AMR\n" 17 | #define MP3_MAGIC_NUMBER "ID3" 18 | 19 | #define PCM_FRAME_SIZE 160 // 8khz 8000*0.02=160 20 | #define MAX_AMR_FRAME_SIZE 32 21 | #define AMR_FRAME_COUNT_PER_SECOND 50 22 | 23 | typedef struct 24 | { 25 | char chChunkID[4]; 26 | int nChunkSize; 27 | }EM_XCHUNKHEADER; 28 | 29 | typedef struct 30 | { 31 | short nFormatTag; 32 | short nChannels; 33 | int nSamplesPerSec; 34 | int nAvgBytesPerSec; 35 | short nBlockAlign; 36 | short nBitsPerSample; 37 | }EM_WAVEFORMAT; 38 | 39 | typedef struct 40 | { 41 | short nFormatTag; 42 | short nChannels; 43 | int nSamplesPerSec; 44 | int nAvgBytesPerSec; 45 | short nBlockAlign; 46 | short nBitsPerSample; 47 | short nExSize; 48 | }EM_WAVEFORMATX; 49 | 50 | typedef struct 51 | { 52 | char chRiffID[4]; 53 | int nRiffSize; 54 | char chRiffFormat[4]; 55 | }EM_RIFFHEADER; 56 | 57 | typedef struct 58 | { 59 | char chFmtID[4]; 60 | int nFmtSize; 61 | EM_WAVEFORMAT wf; 62 | }EM_FMTBLOCK; 63 | 64 | // WAVE音频采样频率是8khz 65 | // 音频样本单元数 = 8000*0.02 = 160 (由采样频率决定) 66 | // 声道数 1 : 160 67 | // 2 : 160*2 = 320 68 | // bps决定样本(sample)大小 69 | // bps = 8 --> 8位 unsigned char 70 | // 16 --> 16位 unsigned short 71 | int EM_EncodeWAVEFileToAMRFile(const char* pchWAVEFilename, const char* pchAMRFileName, int nChannels, int nBitsPerSample); 72 | 73 | // 将AMR文件解码成WAVE文件 74 | int EM_DecodeAMRFileToWAVEFile(const char* pchAMRFileName, const char* pchWAVEFilename); 75 | 76 | //是否是 MP3文件 77 | int isMP3File(const char *filePath); 78 | 79 | //是否是AMR 文件 80 | int isAMRFile(const char *filePath); 81 | 82 | int isAMRFile(const char *filePath); 83 | 84 | 85 | #endif -------------------------------------------------------------------------------- /amrwapper/amrFileCodec.mm: -------------------------------------------------------------------------------- 1 | // 2 | // amrFileCodec.cpp 3 | // amrDemoForiOS 4 | // 5 | // Created by Tang Xiaoping on 9/27/11. 6 | // Copyright 2011 test. All rights reserved. 7 | // 8 | 9 | #include "amrFileCodec.h" 10 | static int amrEncodeMode[] = {4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200}; // amr 编码方式 11 | // 从WAVE文件中跳过WAVE文件头,直接到PCM音频数据 12 | static void SkipToPCMAudioData(FILE* fpwave) 13 | { 14 | EM_RIFFHEADER riff; 15 | EM_FMTBLOCK fmt; 16 | EM_XCHUNKHEADER chunk; 17 | EM_WAVEFORMATX wfx; 18 | int bDataBlock = 0; 19 | 20 | // 1. 读RIFF头 21 | fread(&riff, 1, sizeof(EM_RIFFHEADER), fpwave); 22 | 23 | // 2. 读FMT块 - 如果 fmt.nFmtSize>16 说明需要还有一个附属大小没有读 24 | fread(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); 25 | if ( chunk.nChunkSize>16 ) 26 | { 27 | fread(&wfx, 1, sizeof(EM_WAVEFORMATX), fpwave); 28 | } 29 | else 30 | { 31 | memcpy(fmt.chFmtID, chunk.chChunkID, 4); 32 | fmt.nFmtSize = chunk.nChunkSize; 33 | fread(&fmt.wf, 1, sizeof(EM_WAVEFORMAT), fpwave); 34 | } 35 | 36 | // 3.转到data块 - 有些还有fact块等。 37 | while(!bDataBlock) 38 | { 39 | fread(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); 40 | if ( !memcmp(chunk.chChunkID, "data", 4) ) 41 | { 42 | bDataBlock = 1; 43 | break; 44 | } 45 | // 因为这个不是data块,就跳过块数据 46 | fseek(fpwave, chunk.nChunkSize, SEEK_CUR); 47 | } 48 | } 49 | 50 | // 从WAVE文件读一个完整的PCM音频帧 51 | // 返回值: 0-错误 >0: 完整帧大小 52 | static size_t ReadPCMFrame(short speech[], FILE* fpwave, int nChannels, int nBitsPerSample) 53 | { 54 | size_t nRead = 0; 55 | int x = 0, y=0; 56 | // unsigned short ush1=0, ush2=0, ush=0; 57 | 58 | // 原始PCM音频帧数据 59 | unsigned char pcmFrame_8b1[PCM_FRAME_SIZE]; 60 | unsigned char pcmFrame_8b2[PCM_FRAME_SIZE<<1]; 61 | unsigned short pcmFrame_16b1[PCM_FRAME_SIZE]; 62 | unsigned short pcmFrame_16b2[PCM_FRAME_SIZE<<1]; 63 | 64 | if (nBitsPerSample==8 && nChannels==1) 65 | { 66 | nRead = fread(pcmFrame_8b1, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave); 67 | for(x=0; x> 1; 86 | //speech[y] = (short)((short)ush << 7); 87 | } 88 | } 89 | else 90 | if (nBitsPerSample==16 && nChannels==1) 91 | { 92 | nRead = fread(pcmFrame_16b1, (nBitsPerSample/8), PCM_FRAME_SIZE*nChannels, fpwave); 93 | for(x=0; x> 1; 106 | } 107 | } 108 | 109 | // 如果读到的数据不是一个完整的PCM帧, 就返回0 110 | if (nRead 8位 unsigned char 121 | // 16 --> 16位 unsigned short 122 | int EM_EncodeWAVEFileToAMRFile(const char* pchWAVEFilename, const char* pchAMRFileName, int nChannels, int nBitsPerSample) 123 | { 124 | FILE* fpwave; 125 | FILE* fpamr; 126 | 127 | /* input speech vector */ 128 | short speech[160]; 129 | 130 | /* counters */ 131 | int byte_counter, frames = 0; 132 | size_t bytes = 0; 133 | 134 | /* pointer to encoder state structure */ 135 | void *enstate; 136 | 137 | /* requested mode */ 138 | enum Mode req_mode = MR122; 139 | int dtx = 0; 140 | 141 | /* bitstream filetype */ 142 | unsigned char amrFrame[MAX_AMR_FRAME_SIZE]; 143 | 144 | fpwave = fopen(pchWAVEFilename, "rb"); 145 | if (fpwave == NULL) 146 | { 147 | return 0; 148 | } 149 | 150 | // 创建并初始化amr文件 151 | fpamr = fopen(pchAMRFileName, "wb"); 152 | if (fpamr == NULL) 153 | { 154 | fclose(fpwave); 155 | return 0; 156 | } 157 | /* write magic number to indicate single channel AMR file storage format */ 158 | bytes = fwrite(AMR_MAGIC_NUMBER, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr); 159 | 160 | /* skip to pcm audio data*/ 161 | SkipToPCMAudioData(fpwave); 162 | 163 | enstate = Encoder_Interface_init(dtx); 164 | 165 | while(1) 166 | { 167 | // read one pcm frame 168 | if (!ReadPCMFrame(speech, fpwave, nChannels, nBitsPerSample)) break; 169 | 170 | frames++; 171 | 172 | /* call encoder */ 173 | byte_counter = Encoder_Interface_Encode(enstate, req_mode, speech, amrFrame, 0); 174 | 175 | bytes += byte_counter; 176 | fwrite(amrFrame, sizeof (unsigned char), byte_counter, fpamr ); 177 | } 178 | 179 | Encoder_Interface_exit(enstate); 180 | 181 | fclose(fpamr); 182 | fclose(fpwave); 183 | 184 | return frames; 185 | } 186 | 187 | 188 | 189 | 190 | #pragma mark - Decode 191 | //decode 192 | static void WriteWAVEFileHeader(FILE* fpwave, int nFrame) 193 | { 194 | char tag[10] = ""; 195 | 196 | // 1. 写RIFF头 197 | EM_RIFFHEADER riff; 198 | strcpy(tag, "RIFF"); 199 | memcpy(riff.chRiffID, tag, 4); 200 | riff.nRiffSize = 4 // WAVE 201 | + sizeof(EM_XCHUNKHEADER) // fmt 202 | + sizeof(EM_WAVEFORMATX) // EM_WAVEFORMATX 203 | + sizeof(EM_XCHUNKHEADER) // DATA 204 | + nFrame*160*sizeof(short); // 205 | strcpy(tag, "WAVE"); 206 | memcpy(riff.chRiffFormat, tag, 4); 207 | fwrite(&riff, 1, sizeof(EM_RIFFHEADER), fpwave); 208 | 209 | // 2. 写FMT块 210 | EM_XCHUNKHEADER chunk; 211 | EM_WAVEFORMATX wfx; 212 | strcpy(tag, "fmt "); 213 | memcpy(chunk.chChunkID, tag, 4); 214 | chunk.nChunkSize = sizeof(EM_WAVEFORMATX); 215 | fwrite(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); 216 | memset(&wfx, 0, sizeof(EM_WAVEFORMATX)); 217 | wfx.nFormatTag = 1; 218 | wfx.nChannels = 1; // 单声道 219 | wfx.nSamplesPerSec = 8000; // 8khz 220 | wfx.nAvgBytesPerSec = 16000; 221 | wfx.nBlockAlign = 2; 222 | wfx.nBitsPerSample = 16; // 16位 223 | fwrite(&wfx, 1, sizeof(EM_WAVEFORMATX), fpwave); 224 | 225 | // 3. 写data块头 226 | strcpy(tag, "data"); 227 | memcpy(chunk.chChunkID, tag, 4); 228 | chunk.nChunkSize = nFrame*160*sizeof(short); 229 | fwrite(&chunk, 1, sizeof(EM_XCHUNKHEADER), fpwave); 230 | } 231 | 232 | static const int myround(const double x) 233 | { 234 | return((int)(x+0.5)); 235 | } 236 | 237 | // 根据帧头计算当前帧大小 238 | static int caclAMRFrameSize(unsigned char frameHeader) 239 | { 240 | int mode; 241 | int temp1 = 0; 242 | int temp2 = 0; 243 | int frameSize; 244 | 245 | temp1 = frameHeader; 246 | 247 | // 编码方式编号 = 帧头的3-6位 248 | temp1 &= 0x78; // 0111-1000 249 | temp1 >>= 3; 250 | 251 | mode = amrEncodeMode[temp1]; 252 | 253 | // 计算amr音频数据帧大小 254 | // 原理: amr 一帧对应20ms,那么一秒有50帧的音频数据 255 | temp2 = myround((double)(((double)mode / (double)AMR_FRAME_COUNT_PER_SECOND) / (double)8)); 256 | 257 | frameSize = myround((double)temp2 + 0.5); 258 | return frameSize; 259 | } 260 | 261 | // 读第一个帧 - (参考帧) 262 | // 返回值: 0-出错; 1-正确 263 | static int ReadAMRFrameFirst(FILE* fpamr, unsigned char frameBuffer[], int* stdFrameSize, unsigned char* stdFrameHeader) 264 | { 265 | //memset(frameBuffer, 0, sizeof(frameBuffer)); 266 | 267 | // 先读帧头 268 | fread(stdFrameHeader, 1, sizeof(unsigned char), fpamr); 269 | if (feof(fpamr)) return 0; 270 | 271 | // 根据帧头计算帧大小 272 | *stdFrameSize = caclAMRFrameSize(*stdFrameHeader); 273 | 274 | // 读首帧 275 | frameBuffer[0] = *stdFrameHeader; 276 | fread(&(frameBuffer[1]), 1, (*stdFrameSize-1)*sizeof(unsigned char), fpamr); 277 | if (feof(fpamr)) return 0; 278 | 279 | return 1; 280 | } 281 | 282 | // 返回值: 0-出错; 1-正确 283 | static int ReadAMRFrame(FILE* fpamr, unsigned char frameBuffer[], int stdFrameSize, unsigned char stdFrameHeader) 284 | { 285 | size_t bytes = 0; 286 | unsigned char frameHeader; // 帧头 287 | 288 | //memset(frameBuffer, 0, sizeof(frameBuffer)); 289 | 290 | // 读帧头 291 | // 如果是坏帧(不是标准帧头),则继续读下一个字节,直到读到标准帧头 292 | while(1) 293 | { 294 | bytes = fread(&frameHeader, 1, sizeof(unsigned char), fpamr); 295 | if (feof(fpamr)) return 0; 296 | if (frameHeader == stdFrameHeader) break; 297 | } 298 | 299 | // 读该帧的语音数据(帧头已经读过) 300 | frameBuffer[0] = frameHeader; 301 | bytes = fread(&(frameBuffer[1]), 1, (stdFrameSize-1)*sizeof(unsigned char), fpamr); 302 | if (feof(fpamr)) return 0; 303 | 304 | return 1; 305 | } 306 | 307 | // 将AMR文件解码成WAVE文件 308 | int EM_DecodeAMRFileToWAVEFile(const char* pchAMRFileName, const char* pchWAVEFilename) 309 | { 310 | 311 | 312 | FILE* fpamr = NULL; 313 | FILE* fpwave = NULL; 314 | char magic[8]; 315 | void * destate; 316 | int nFrameCount = 0; 317 | int stdFrameSize; 318 | unsigned char stdFrameHeader; 319 | 320 | unsigned char amrFrame[MAX_AMR_FRAME_SIZE]; 321 | short pcmFrame[PCM_FRAME_SIZE]; 322 | 323 | fpamr = fopen(pchAMRFileName, "rb"); 324 | 325 | if ( fpamr==NULL ) return 0; 326 | 327 | // 检查amr文件头 328 | fread(magic, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr); 329 | if (strncmp(magic, AMR_MAGIC_NUMBER, strlen(AMR_MAGIC_NUMBER))) 330 | { 331 | fclose(fpamr); 332 | return 0; 333 | } 334 | 335 | // 创建并初始化WAVE文件 336 | // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 337 | // NSString *documentPath = [paths objectAtIndex:0]; 338 | // NSString *docFilePath = [documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%s", pchWAVEFilename]]; 339 | // NSLog(@"documentPath=%@", documentPath); 340 | // 341 | // fpwave = fopen([docFilePath cStringUsingEncoding:NSASCIIStringEncoding], "wb"); 342 | fpwave = fopen(pchWAVEFilename,"wb"); 343 | 344 | WriteWAVEFileHeader(fpwave, nFrameCount); 345 | 346 | /* init decoder */ 347 | destate = Decoder_Interface_init(); 348 | 349 | // 读第一帧 - 作为参考帧 350 | memset(amrFrame, 0, MAX_AMR_FRAME_SIZE); 351 | memset(pcmFrame, 0, PCM_FRAME_SIZE); 352 | ReadAMRFrameFirst(fpamr, amrFrame, &stdFrameSize, &stdFrameHeader); 353 | 354 | // 解码一个AMR音频帧成PCM数据 355 | Decoder_Interface_Decode(destate, amrFrame, pcmFrame, 0); 356 | nFrameCount++; 357 | fwrite(pcmFrame, sizeof(short), PCM_FRAME_SIZE, fpwave); 358 | 359 | // 逐帧解码AMR并写到WAVE文件里 360 | while(1) 361 | { 362 | memset(amrFrame, 0, MAX_AMR_FRAME_SIZE); 363 | memset(pcmFrame, 0, PCM_FRAME_SIZE); 364 | if (!ReadAMRFrame(fpamr, amrFrame, stdFrameSize, stdFrameHeader)) break; 365 | 366 | // 解码一个AMR音频帧成PCM数据 (8k-16b-单声道) 367 | Decoder_Interface_Decode(destate, amrFrame, pcmFrame, 0); 368 | nFrameCount++; 369 | fwrite(pcmFrame, sizeof(short), PCM_FRAME_SIZE, fpwave); 370 | } 371 | //NSLog(@"frame = %d", nFrameCount); 372 | Decoder_Interface_exit(destate); 373 | 374 | fclose(fpwave); 375 | 376 | // 重写WAVE文件头 377 | // fpwave = fopen([docFilePath cStringUsingEncoding:NSASCIIStringEncoding], "r+"); 378 | fpwave = fopen(pchWAVEFilename, "r+"); 379 | WriteWAVEFileHeader(fpwave, nFrameCount); 380 | fclose(fpwave); 381 | 382 | return nFrameCount; 383 | } 384 | 385 | int isMP3File(const char *filePath){ 386 | FILE* fpamr = NULL; 387 | char magic[8]; 388 | fpamr = fopen(filePath, "rb"); 389 | if (fpamr==NULL) return 0; 390 | int isMp3 = 0; 391 | fread(magic, sizeof(char), strlen(MP3_MAGIC_NUMBER), fpamr); 392 | if (!strncmp(magic, MP3_MAGIC_NUMBER, strlen(MP3_MAGIC_NUMBER))) 393 | { 394 | isMp3 = 1; 395 | } 396 | fclose(fpamr); 397 | return isMp3; 398 | } 399 | 400 | 401 | int isAMRFile(const char *filePath){ 402 | FILE* fpamr = NULL; 403 | char magic[8]; 404 | fpamr = fopen(filePath, "rb"); 405 | if (fpamr==NULL) return 0; 406 | int isAmr = 0; 407 | fread(magic, sizeof(char), strlen(AMR_MAGIC_NUMBER), fpamr); 408 | if (!strncmp(magic, AMR_MAGIC_NUMBER, strlen(AMR_MAGIC_NUMBER))) 409 | { 410 | isAmr = 1; 411 | } 412 | fclose(fpamr); 413 | return isAmr; 414 | } 415 | -------------------------------------------------------------------------------- /amrwapper/wav.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------ 2 | * Copyright (C) 2009 Martin Storsjo 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. 14 | * See the License for the specific language governing permissions 15 | * and limitations under the License. 16 | * ------------------------------------------------------------------- 17 | */ 18 | 19 | #ifndef WAV_H 20 | #define WAV_H 21 | 22 | #include 23 | 24 | class WavWriter { 25 | public: 26 | WavWriter(const char *filename, int sampleRate, int bitsPerSample, int channels); 27 | ~WavWriter(); 28 | 29 | void writeData(const unsigned char* data, int length); 30 | 31 | private: 32 | void writeString(const char *str); 33 | void writeInt32(int value); 34 | void writeInt16(int value); 35 | 36 | void writeHeader(int length); 37 | 38 | FILE *wav; 39 | int dataLength; 40 | 41 | int sampleRate; 42 | int bitsPerSample; 43 | int channels; 44 | }; 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /amrwapper/wav.mm: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------ 2 | * Copyright (C) 2009 Martin Storsjo 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. 14 | * See the License for the specific language governing permissions 15 | * and limitations under the License. 16 | * ------------------------------------------------------------------- 17 | */ 18 | 19 | #import 20 | #include "wav.h" 21 | 22 | void WavWriter::writeString(const char *str) { 23 | fputc(str[0], wav); 24 | fputc(str[1], wav); 25 | fputc(str[2], wav); 26 | fputc(str[3], wav); 27 | } 28 | 29 | void WavWriter::writeInt32(int value) { 30 | fputc((value >> 0) & 0xff, wav); 31 | fputc((value >> 8) & 0xff, wav); 32 | fputc((value >> 16) & 0xff, wav); 33 | fputc((value >> 24) & 0xff, wav); 34 | } 35 | 36 | void WavWriter::writeInt16(int value) { 37 | fputc((value >> 0) & 0xff, wav); 38 | fputc((value >> 8) & 0xff, wav); 39 | } 40 | 41 | void WavWriter::writeHeader(int length) { 42 | writeString("RIFF"); 43 | writeInt32(4 + 8 + 20 + 8 + length); //将16改为20 44 | writeString("WAVE"); 45 | 46 | writeString("fmt "); 47 | writeInt32(20); 48 | 49 | int bytesPerFrame = bitsPerSample/8*channels; 50 | int bytesPerSec = bytesPerFrame*sampleRate; 51 | writeInt16(1); // Format 52 | writeInt16(channels); // Channels 53 | writeInt32(sampleRate); // Samplerate 54 | writeInt32(bytesPerSec); // Bytes per sec 55 | writeInt16(bytesPerFrame); // Bytes per frame 56 | writeInt16(bitsPerSample); // Bits per sample 57 | 58 | writeInt32(0); //这儿需要字节对齐 nExSize 59 | 60 | writeString("data"); 61 | writeInt32(length); 62 | } 63 | 64 | WavWriter::WavWriter(const char *filename, int sampleRate, int bitsPerSample, int channels) 65 | { 66 | 67 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 68 | NSString *documentPath = [paths objectAtIndex:0]; 69 | NSString *docFilePath = [documentPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%s", filename]]; 70 | //NSLog(@"documentPath=%@", documentPath); 71 | 72 | wav = fopen([docFilePath cStringUsingEncoding:NSASCIIStringEncoding], "wb"); 73 | if (wav == NULL) 74 | return; 75 | dataLength = 0; 76 | this->sampleRate = sampleRate; 77 | this->bitsPerSample = bitsPerSample; 78 | this->channels = channels; 79 | 80 | writeHeader(dataLength); 81 | } 82 | 83 | WavWriter::~WavWriter() { 84 | if (wav == NULL) 85 | return; 86 | fseek(wav, 0, SEEK_SET); 87 | writeHeader(dataLength); 88 | fclose(wav); 89 | } 90 | 91 | void WavWriter::writeData(const unsigned char* data, int length) { 92 | if (wav == NULL) 93 | return; 94 | fwrite(data, length, 1, wav); 95 | dataLength += length; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /opencore-amrnb/interf_dec.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------ 2 | * Copyright (C) 2009 Martin Storsjo 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. 14 | * See the License for the specific language governing permissions 15 | * and limitations under the License. 16 | * ------------------------------------------------------------------- 17 | */ 18 | 19 | #ifndef OPENCORE_AMRNB_INTERF_DEC_H 20 | #define OPENCORE_AMRNB_INTERF_DEC_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | void* Decoder_Interface_init(void); 27 | void Decoder_Interface_exit(void* state); 28 | void Decoder_Interface_Decode(void* state, const unsigned char* in, short* out, int bfi); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /opencore-amrnb/interf_enc.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------ 2 | * Copyright (C) 2009 Martin Storsjo 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. 14 | * See the License for the specific language governing permissions 15 | * and limitations under the License. 16 | * ------------------------------------------------------------------- 17 | */ 18 | 19 | #ifndef OPENCORE_AMRNB_INTERF_ENC_H 20 | #define OPENCORE_AMRNB_INTERF_ENC_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #ifndef AMRNB_WRAPPER_INTERNAL 27 | /* Copied from enc/src/gsmamr_enc.h */ 28 | enum Mode { 29 | MR475 = 0,/* 4.75 kbps */ 30 | MR515, /* 5.15 kbps */ 31 | MR59, /* 5.90 kbps */ 32 | MR67, /* 6.70 kbps */ 33 | MR74, /* 7.40 kbps */ 34 | MR795, /* 7.95 kbps */ 35 | MR102, /* 10.2 kbps */ 36 | MR122, /* 12.2 kbps */ 37 | MRDTX, /* DTX */ 38 | N_MODES /* Not Used */ 39 | }; 40 | #endif 41 | 42 | void* Encoder_Interface_init(int dtx); 43 | void Encoder_Interface_exit(void* state); 44 | int Encoder_Interface_Encode(void* state, enum Mode mode, const short* speech, unsigned char* out, int forceSpeech); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /opencore-amrnb/libopencore-amrnb.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElderBroCode/VoiceConvert/af907ce6f6488f1b4d3486c8b25e0479a69efa0f/opencore-amrnb/libopencore-amrnb.a -------------------------------------------------------------------------------- /opencore-amrwb/dec_if.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------ 2 | * Copyright (C) 2009 Martin Storsjo 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. 14 | * See the License for the specific language governing permissions 15 | * and limitations under the License. 16 | * ------------------------------------------------------------------- 17 | */ 18 | 19 | #ifndef OPENCORE_AMRWB_DEC_IF_H 20 | #define OPENCORE_AMRWB_DEC_IF_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #define _good_frame 0 27 | 28 | void* D_IF_init(void); 29 | void D_IF_decode(void* state, const unsigned char* bits, short* synth, int bfi); 30 | void D_IF_exit(void* state); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /opencore-amrwb/if_rom.h: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------ 2 | * Copyright (C) 2009 Martin Storsjo 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. 14 | * See the License for the specific language governing permissions 15 | * and limitations under the License. 16 | * ------------------------------------------------------------------- 17 | */ 18 | 19 | #ifndef OPENCORE_AMRWB_IF_ROM_H 20 | #define OPENCORE_AMRWB_IF_ROM_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #include 27 | typedef int16_t Word16; 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /opencore-amrwb/libopencore-amrwb.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElderBroCode/VoiceConvert/af907ce6f6488f1b4d3486c8b25e0479a69efa0f/opencore-amrwb/libopencore-amrwb.a -------------------------------------------------------------------------------- /sayhi.txt: -------------------------------------------------------------------------------- 1 | hello 2 | --------------------------------------------------------------------------------