im client iOS端将android端录制的格式为amr的语音转码为wav格式
用到一个开源的库:opencore-amr for ios
https://github.com/feuvan/opencore-amr-iOS
1.下载后运行xcode脚本,
2.脚本运行完成后,看到目录下test里面有例子,即解压和压缩的例子
我试了下,用amrn-dec.c
+(DDMessageEntity *)makeMessageFromStream:(DDDataInputStream *)bodyData { int32_t seqNo = [bodyData readInt]; NSString *fromUserId = [bodyData readUTF]; NSString *toUserId = [bodyData readUTF]; int32_t msgTime = [bodyData readInt]; int8_t msgType = [bodyData readChar]; //int8_t msgRenderType = [bodyData readChar]; DDMessageEntity *msg = [[DDMessageEntity alloc ] init]; msg.msgType = msgType; msg.msgContentType = msgType; NSString* messageContent = nil; NSMutableDictionary* info = [[NSMutableDictionary alloc] init]; if (msgType == DDMessageTypeVoice || msgType == DDGroup_MessageTypeVoice) { if (msgType ==DDMessageTypeVoice) { msg.msgType = MESSAGE_TYPE_SINGLE; msg.msgContentType =DDMessageTypeVoice; }else{ msg.msgType = MESSAGE_TYPE_TEMP_GROUP; msg.msgContentType =DDGroup_MessageTypeVoice; } int32_t dataLength = [bodyData readInt]; NSData* data = [bodyData readDataWithLength:dataLength]; NSData* voiceData = [data subdataWithRange:NSMakeRange(4, [data length] - 4)]; NSString* filename = [NSString stringWithString:[Encapsulator defaultFileName]]; //....---------------------********* NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *voiceDirectory = [documentsDirectory stringByAppendingPathComponent:@"voice"]; if ( ! [[NSFileManager defaultManager] fileExistsAtPath:voiceDirectory]) { [[NSFileManager defaultManager] createDirectoryAtPath:voiceDirectory withIntermediateDirectories:YES attributes:nil error:NULL]; } NSString* fileAmrName = [voiceDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%.0f.amr", [[NSDate date] timeIntervalSince1970]]]; NSString* fileWavName = [voiceDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%.0f.wav", [[NSDate date] timeIntervalSince1970]]]; if ([voiceData writeToFile:fileAmrName atomically:YES]) { int decode = [MKServerHelper amrwbDec:2 sourcefile:fileAmrName AndTargetFile:fileWavName]; if (decode == 0) { NSLog(@"格式转换成功"); } } else { NSLog(@"语音存储出错"); } //....---------------------********* if ([voiceData writeToFile:filename atomically:YES]) { messageContent = filename; } else { messageContent = @"语音存储出错"; } NSData* voiceLengthData = [data subdataWithRange:NSMakeRange(0, 4)]; int8_t ch1; [voiceLengthData getBytes:&ch1 range:NSMakeRange(0,1)]; ch1 = ch1 & 0x0ff; int8_t ch2; [voiceLengthData getBytes:&ch2 range:NSMakeRange(1,1)]; ch2 = ch2 & 0x0ff; int32_t ch3; [voiceLengthData getBytes:&ch3 range:NSMakeRange(2,1)]; ch3 = ch3 & 0x0ff; int32_t ch4; [voiceLengthData getBytes:&ch4 range:NSMakeRange(3,1)]; ch4 = ch4 & 0x0ff; if ((ch1 | ch2 | ch3 | ch4) < 0){ @throw [NSException exceptionWithName:@"Exception" reason:@"EOFException" userInfo:nil]; } int voiceLength = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); [info setObject:@(voiceLength) forKey:VOICE_LENGTH]; [info setObject:@(0) forKey:DDVOICE_PLAYED]; }else { messageContent = (NSString *)[bodyData readUTF]; if ([messageContent hasPrefix:DD_MESSAGE_IMAGE_PREFIX]) { msg.msgContentType = DDMessageTypeImage; } } NSString *attach = [bodyData readUTF]; msg.msgID = [DDMessageModule getMessageID]; msg.seqNo = seqNo; msg.msgTime = msgTime; msg.toUserID=toUserId; msg.msgContent = [msg getNewMessageContentFromContent:messageContent]; msg.attach = attach; if([msg isGroupMessage]) { msg.sessionId = toUserId; //群聊时,toUserId表示会话ID msg.senderId = fromUserId; //群聊时,fromUserId表示发送者I } else { msg.sessionId = fromUserId; //单人时,fromUserId表示发送者ID,作为会话id msg.senderId = fromUserId; //单人时,fromUserId表示发送者ID } if ([msg.sessionId isEqualToString:TheRuntime.userID]) { msg.sessionId = toUserId; } msg.info=info; return msg; }
Helper:
+(int )amrwbDec :(int ) argc sourcefile:(NSString*)sourceFile AndTargetFile:(NSString*) targetFile { // char *argv[10]; const int sizes[] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 6, 5, 5, 0, 0, 0, 0 }; FILE* in; char header[6]; int n; void *wav, *amr; in = fopen([sourceFile UTF8String] , "rb"); if (!in) { perror([sourceFile UTF8String]); return 1; } n = fread(header, 1, 6, in); if (n != 6 || memcmp(header, "#!AMR\n", 6)) { fprintf(stderr, "Bad header\n"); return 1; } wav = wav_write_open([targetFile UTF8String], 8000, 16, 1); if (!wav) { fprintf(stderr, "Unable to open %s\n", [targetFile UTF8String]); return 1; } amr = Decoder_Interface_init(); while (1) { uint8_t buffer[500], littleendian[320], *ptr; int size, i; int16_t outbuffer[160]; /* Read the mode byte */ n = fread(buffer, 1, 1, in); if (n <= 0) break; /* Find the packet size */ size = sizes[(buffer[0] >> 3) & 0x0f]; n = fread(buffer + 1, 1, size, in); if (n != size) break; /* Decode the packet */ Decoder_Interface_Decode(amr, buffer, outbuffer, 0); /* Convert to little endian and write to wav */ ptr = littleendian; for (i = 0; i < 160; i++) { *ptr++ = (outbuffer[i] >> 0) & 0xff; *ptr++ = (outbuffer[i] >> 8) & 0xff; } wav_write_data(wav, littleendian, 320); } fclose(in); Decoder_Interface_exit(amr); wav_write_close(wav); return 0; }
生成的.wav文件用itools打开该应用,到voice目录下就可以找到,
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。