AAC文件转为PCM文件,转文字,报错-3005
grp8878093 发布于2018-11 浏览:2818 回复:1
0
收藏

一直报错,-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);

}

 

收藏
点赞
0
个赞
共1条回复 最后由用户已被禁言回复于2022-04
#2fujiayi1984回复于2018-11

aac文件转换为pcm格式后,自行先听下

0
TOP
切换版块