一直报错,-3005
质量低
-(void)decodeAACFilePath:(NSString *)aacPath{
MyAudioConverterSettings audioConverterSettings = {0};
// open the input audio file
CFStringRef path;
// NSString *audioURL=[[NSBundle mainBundle] pathForResource:@"abc" ofType:@"aac"];
path = CFStringCreateWithCString (NULL, [aacPath UTF8String],
kCFStringEncodingUTF8);
CFURLRef inputFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, false);
CheckResult (AudioFileOpenURL(inputFileURL, kAudioFileReadPermission , 0, &audioConverterSettings.inputFile),
"AudioFileOpenURL failed");
CFRelease(inputFileURL);
// get the audio data format from the file
UInt32 propSize = sizeof(audioConverterSettings.inputFormat);
CheckResult (AudioFileGetProperty(audioConverterSettings.inputFile, kAudioFilePropertyDataFormat, &propSize, &audioConverterSettings.inputFormat),
"couldn't get file's data format");
// get the total number of packets in the file
propSize = sizeof(audioConverterSettings.inputFilePacketCount);
CheckResult (AudioFileGetProperty(audioConverterSettings.inputFile, kAudioFilePropertyAudioDataPacketCount, &propSize, &audioConverterSettings.inputFilePacketCount),
"couldn't get file's packet count");
// get size of the largest possible packet
propSize = sizeof(audioConverterSettings.inputFilePacketMaxSize);
CheckResult(AudioFileGetProperty(audioConverterSettings.inputFile, kAudioFilePropertyMaximumPacketSize, &propSize, &audioConverterSettings.inputFilePacketMaxSize),
"couldn't get file's max packet size");
// define the ouput format. AudioConverter requires that one of the data formats be LPCM
audioConverterSettings.outputFormat.mSampleRate = 16000;
audioConverterSettings.outputFormat.mFormatID = kAudioFormatLinearPCM;
audioConverterSettings.outputFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioConverterSettings.outputFormat.mBytesPerPacket = 2;
audioConverterSettings.outputFormat.mFramesPerPacket = 1;
audioConverterSettings.outputFormat.mBytesPerFrame = 2;
audioConverterSettings.outputFormat.mChannelsPerFrame = 1;
audioConverterSettings.outputFormat.mBitsPerChannel = 16;
// create output file
// KEVIN: TODO: this fails if file exists. isn't there an overwrite flag we can use?
CFStringRef outputPath;
NSString *outputFile = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"abc.pcm"];
// 有就移除掉
[[NSFileManager defaultManager] removeItemAtPath:outputFile error:nil];
// 移除之后再创建
[[NSFileManager defaultManager] createFileAtPath:outputFile contents:nil attributes:nil];
outputPath = CFStringCreateWithCString (NULL, [outputFile UTF8String],
kCFStringEncodingUTF8);
CFURLRef outputFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, outputPath, kCFURLPOSIXPathStyle, false);
CheckResult (AudioFileCreateWithURL(outputFileURL, kAudioFileAIFFType, &audioConverterSettings.outputFormat, kAudioFileFlags_EraseFile, &audioConverterSettings.outputFile),
"AudioFileCreateWithURL failed");
CFRelease(outputFileURL);
fprintf(stdout, "Converting...\n");
Convert(&audioConverterSettings);
cleanup:
AudioFileClose(audioConverterSettings.inputFile);
AudioFileClose(audioConverterSettings.outputFile);
printf("Done\r");
#pragma mark -- 校验转换后的音频文件类型
NSFileManager *manager1 = [NSFileManager defaultManager];
NSURL *endpath1 = [[manager1 URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSURL *url1 = [endpath1 URLByAppendingPathComponent:@"abc.pcm"];
OSStatus status1 = AudioFileOpenURL((__bridge CFURLRef)url1, kAudioFileReadPermission, 0, &audioFileID); //Open an existing audio file specified by a URL.
if (status1 != noErr) {
NSLog(@"打开文件失败 %@", url1);
return ;
}
//audioStreamBasicDescrpition 结构体:定义了采样率、格式、每个包的数量等
uint32_t size = sizeof(audioStreamBasicDescrpition);
//获取音频文件中指定属性的值
status1 = AudioFileGetProperty(audioFileID, kAudioFilePropertyDataFormat, &size, &audioStreamBasicDescrpition); // Gets the value of an audio file property.
NSAssert(status1 == noErr, @"error");
#pragma mark -- 语音转文字,放入转换后的音频pcm文件
[self transformVoiceToString:outputFile];
NSFileManager *manager = [NSFileManager defaultManager];
NSURL *endpath = [[manager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSURL *url = [endpath URLByAppendingPathComponent:@"abc.pcm"];
NSData *data1 = [NSData dataWithContentsOfFile:outputFile];
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
//播放转换的数据
// NSString* filepath123 = [[NSBundle mainBundle] pathForResource:@"16kttt" ofType:@"pcm"];
[[ChatSoundPlayer sharedInstance] playWith:[NSData dataWithContentsOfFile:outputFile] finish:^{
NSLog(@"");
}];
});
NSLog(@"");
}
void Convert(MyAudioConverterSettings *mySettings)
{
// create audioConverter object
AudioConverterRef audioConverter;
CheckResult (AudioConverterNew(&mySettings->inputFormat, &mySettings->outputFormat, &audioConverter),
"AudioConveterNew failed");
// allocate packet descriptions if the input file is VBR
UInt32 packetsPerBuffer = 0;
UInt32 outputBufferSize = 32 * 1024; // 32 KB is a good starting point
UInt32 sizePerPacket = mySettings->inputFormat.mBytesPerPacket;
if (sizePerPacket == 0)
{
UInt32 size = sizeof(sizePerPacket);
CheckResult(AudioConverterGetProperty(audioConverter, kAudioConverterPropertyMaximumOutputPacketSize, &size, &sizePerPacket),
"Couldn't get kAudioConverterPropertyMaximumOutputPacketSize");
// make sure the buffer is large enough to hold at least one packet
if (sizePerPacket > outputBufferSize)
outputBufferSize = sizePerPacket;
packetsPerBuffer = outputBufferSize / sizePerPacket;
mySettings->inputFilePacketDescriptions = (AudioStreamPacketDescription*)malloc(sizeof(AudioStreamPacketDescription) * packetsPerBuffer);
}
else
{
packetsPerBuffer = outputBufferSize / sizePerPacket;
}
// allocate destination buffer
UInt8 *outputBuffer = (UInt8 *)malloc(sizeof(UInt8) * outputBufferSize); // CHRIS: not sizeof(UInt8*). check book text!
UInt32 outputFilePacketPosition = 0; //in bytes
while(1)
{
// wrap the destination buffer in an AudioBufferList
AudioBufferList convertedData = {0};
// memset(&convertedData, 0, sizeof(AudioBufferList));
// memset(&convertedData.mBuffers[0], 0, sizeof(AudioBuffer));
convertedData.mNumberBuffers = 1;
convertedData.mBuffers[0].mNumberChannels = mySettings->inputFormat.mChannelsPerFrame;
convertedData.mBuffers[0].mDataByteSize = outputBufferSize;
convertedData.mBuffers[0].mData = outputBuffer;
// now call the audioConverter to transcode the data. This function will call
// the callback function as many times as required to fulfill the request.
UInt32 ioOutputDataPacketSize = 1;
UInt32 ioOutputDataPackets = packetsPerBuffer;
AudioStreamPacketDescription *outPacketDescription = NULL;
outPacketDescription = (AudioStreamPacketDescription*)malloc(sizeof(AudioStreamPacketDescription) * ioOutputDataPacketSize);
OSStatus error = AudioConverterFillComplexBuffer(audioConverter,
MyAudioConverterCallback,
mySettings,
&ioOutputDataPackets,
&convertedData,
outPacketDescription);
// (mySettings->inputFilePacketDescriptions ? mySettings->inputFilePacketDescriptions : nil));
if (error || !ioOutputDataPackets)
{
fprintf(stderr, "err: %ld, packets: %ld\n", error, ioOutputDataPackets);
break; // this is our termination condition
}
// write the converted data to the output file
// KEVIN: QUESTION: 3rd arg seems like it should be a byte count, not packets. why does this work?
CheckResult (AudioFileWritePackets(mySettings->outputFile,
FALSE,
ioOutputDataPackets,
NULL,
outputFilePacketPosition / mySettings->outputFormat.mBytesPerPacket,
&ioOutputDataPackets,
convertedData.mBuffers[0].mData),
"Couldn't write packets to file");
//outputFilePacketPosition / mySettings->outputFormat.mBytesPerPacket,
// advance the output file write location
outputFilePacketPosition += (ioOutputDataPackets * mySettings->outputFormat.mBytesPerPacket);
}
AudioConverterDispose(audioConverter);
}
OSStatus MyAudioConverterCallback(AudioConverterRef inAudioConverter,
UInt32 *ioDataPacketCount,
AudioBufferList *ioData,
AudioStreamPacketDescription **outDataPacketDescription,
void *inUserData)
{
MyAudioConverterSettings *audioConverterSettings = (MyAudioConverterSettings *)inUserData;
// initialize in case of failure
ioData->mBuffers[0].mData = NULL;
ioData->mBuffers[0].mDataByteSize = 0;
// if there are not enough packets to satisfy request, then read what's left
if (audioConverterSettings->inputFilePacketIndex + *ioDataPacketCount > audioConverterSettings->inputFilePacketCount)
*ioDataPacketCount = audioConverterSettings->inputFilePacketCount - audioConverterSettings->inputFilePacketIndex;
if(*ioDataPacketCount == 0)
return noErr;
if (audioConverterSettings->sourceBuffer != NULL)
{
free(audioConverterSettings->sourceBuffer);
audioConverterSettings->sourceBuffer = NULL;
}
audioConverterSettings->sourceBuffer = (void *)calloc(1, *ioDataPacketCount * audioConverterSettings->inputFilePacketMaxSize);
UInt32 outByteCount = 0;
OSStatus result = AudioFileReadPackets(audioConverterSettings->inputFile,
true,
&outByteCount,
audioConverterSettings->inputFilePacketDescriptions,
audioConverterSettings->inputFilePacketIndex,
ioDataPacketCount,
audioConverterSettings->sourceBuffer);
// it's not an error if we just read the remainder of the file
#ifdef MAC_OS_X_VERSION_10_7
if (result == kAudioFileEndOfFileError && *ioDataPacketCount) result = noErr;
#else
if (result == eofErr && *ioDataPacketCount) result = noErr;
#endif
else if (result != noErr) return result;
audioConverterSettings->inputFilePacketIndex += *ioDataPacketCount;
// KEVIN: in "// initialize in case of failure", we assumed there was only 1
// buffer (since we set it up ourselves in Convert()). so why be careful to
// iterate over potentially multiple buffers here?
/*
UInt32 bufferIndex;
for (bufferIndex = 0; bufferIndex < ioData->mNumberBuffers; bufferIndex++)
{
ioData->mBuffers[bufferIndex].mData = audioConverterSettings->sourceBuffer;
ioData->mBuffers[bufferIndex].mDataByteSize = outByteCount;
}
*/
// chris' hacky asssume-one-buffer equivalent
ioData->mBuffers[0].mData = audioConverterSettings->sourceBuffer;
ioData->mBuffers[0].mDataByteSize = outByteCount;
if (outDataPacketDescription)
*outDataPacketDescription = audioConverterSettings->inputFilePacketDescriptions;
return result;
}
#pragma mark -- 接入百度语音转文字,代理返回文字
-(CNVoiceToText *)vt{
if (_vt == nil) {
_vt = [[CNVoiceToText alloc] initData];
[_vt setParameter:@[BDAppKey,BDSecret]];
[_vt setAppId:BDAppId];
_vt.delegate = self;
}
return _vt;
}
- (void)transformVoiceToString:(NSString *)filePath{
[self.vt fileRecognition:filePath];
}
- (void)voiceRecognitionClientWorkStatus:(int)workStatus obj:(id)aObj{
if (workStatus == 4 || workStatus == 5) {
if ([aObj isKindOfClass:[NSDictionary class]]) {
NSString *str = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:(NSDictionary *)aObj
options:NSJSONWritingPrettyPrinted
error:nil] encoding:NSUTF8StringEncoding];
if (str.length > 0) {
NSLog(@"%@",str);
}
}
}
}
static void CheckResult(OSStatus result, const char *operation)
{
if (result == noErr) return;
char errorString[20];
// see if it appears to be a 4-char-code
*(UInt32 *)(errorString + 1) = CFSwapInt32HostToBig(result);
if (isprint(errorString[1]) && isprint(errorString[2]) && isprint(errorString[3]) && isprint(errorString[4])) {
errorString[0] = errorString[5] = '\'';
errorString[6] = '\0';
} else{
// no, format it as an integer
sprintf(errorString, "%d", (int)result);
}
fprintf(stderr, "Error: %s (%s)\n", operation, errorString);
exit(1);
}
aac文件转换为pcm格式后,自行先听下