我一直在尝试在 iPad 2 上的 iOS 5 中的 renderCallback 中从 RemoteIO 单元直接录制到 AAC。我看到了相互矛盾的信息,说这是不可能的并且是可能的(在评论 here 中)。我想要这样做的原因是因为录制到 PCM 需要大量的磁盘空间来录制任何长度的内容——即使它后来被转换为 AAC。

不过我也准备放弃了。我已经浏览了 Google、SO、Core Audio 书籍和 Apple Core-Audio 邮件列表和论坛,并且已经达到了没有任何错误的地步 - 并且正在将某些内容录制到磁盘,但生成的文件无法播放。模拟器和设备上都是这种情况。

所以...如果有人对此有经验,我将非常感谢朝着正确方向的插入。设置是RemoteIO正在播放AUSamplers的输出,并且工作正常。

这是我在下面的代码中正在做的

  • 指定 remoteIO 的 AudioStreamBasicDescription 格式
    单位到kAudioFormatLinearPCM
  • 创建并指定ExtAudioFileRef的目标格式
    通过从 RemoteIO 单元
  • 获取来指定客户端格式
  • 为RemoteID单元
  • 指定renderCallback
  • 在renderCallback中,将数据写入kAudioUnitRenderAction_PostRender阶段

  • 正如我所说,我没有收到任何错误,生成的音频文件大小显示正在写入某些内容,但该文件无法播放。也许我的格式搞砸了?

    无论如何,这是我在瓶子里和/或“Be Here Dragons”旗帜中的信息,给任何冒着 Core-Audio 黑暗水域的人。

    //尝试播放文件时遇到的不愉快的消息:

    //远程IO设置的一部分
        // Enable IO for recording
    
    UInt32 flag = 1;
    result = AudioUnitSetProperty(ioUnit,
                                  kAudioOutputUnitProperty_EnableIO,
                                  kAudioUnitScope_Input,
                                  kInputBus, // == 1
                                  &flag,
                                  sizeof(flag));
    if (noErr != result) {[self printErrorMessage: @"Enable IO for recording" withStatus: result]; return;}
    
    // Describe format - - - - - - - - - -
    size_t bytesPerSample = sizeof (AudioUnitSampleType);
    AudioStreamBasicDescription audioFormat;
    memset(&audioFormat, 0, sizeof(audioFormat));
    audioFormat.mSampleRate   = 44100.00;
    audioFormat.mFormatID     = kAudioFormatLinearPCM;
    audioFormat.mFormatFlags    = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    audioFormat.mFramesPerPacket = 1;
    audioFormat.mChannelsPerFrame = 1;
    audioFormat.mBitsPerChannel   = 16;
    audioFormat.mBytesPerPacket   = 2;
    audioFormat.mBytesPerFrame    = 2;
    
    result = AudioUnitSetProperty(ioUnit,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Output,
                                  kInputBus, // == 1
                                  &audioFormat,
                                  sizeof(audioFormat));
    
    
    result = AudioUnitSetProperty(ioUnit,
                                  kAudioUnitProperty_StreamFormat,
                                  kAudioUnitScope_Input,
                                  kOutputBus, // == 0
                                  &audioFormat,
                                  sizeof(audioFormat));
    

    //设置文件和渲染回调函数
     - (void)startRecordingAAC
    {
    
    OSStatus result;
    
    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *recordFile = [documentsDirectory stringByAppendingPathComponent: @"audio.m4a"];
    
    CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
                                                            (__bridge   CFStringRef)recordFile,
                                                            kCFURLPOSIXPathStyle,
                                                            false);
    
    AudioStreamBasicDescription destinationFormat;
    memset(&destinationFormat, 0, sizeof(destinationFormat));
    destinationFormat.mChannelsPerFrame = 2;
    destinationFormat.mFormatID = kAudioFormatMPEG4AAC;
    UInt32 size = sizeof(destinationFormat);
    result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat);
    if(result) printf("AudioFormatGetProperty %ld \n", result);
    
    
    result = ExtAudioFileCreateWithURL(destinationURL,
                                       kAudioFileM4AType,
                                       &destinationFormat,
                                       NULL,
                                       kAudioFileFlags_EraseFile,
                                       &extAudioFileRef);
    if(result) printf("ExtAudioFileCreateWithURL %ld \n", result);
    
    AudioStreamBasicDescription clientFormat;
    memset(&clientFormat, 0, sizeof(clientFormat));
    
    
    result = AudioUnitGetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, & clientFormat, &size);
     if(result) printf("AudioUnitGetProperty %ld \n", result);
    
    result = ExtAudioFileSetProperty(extAudioFileRef,kExtAudioFileProperty_ClientDataFormat,sizeof(clientFormat),&clientFormat);
    if(result) printf("ExtAudioFileSetProperty %ld \n", result);
    
    result =  ExtAudioFileWriteAsync(extAudioFileRef, 0, NULL);
    if (result) {[self printErrorMessage: @"ExtAudioFileWriteAsync error" withStatus: result];}
    
    result = AudioUnitAddRenderNotify(ioUnit, renderCallback, (__bridge void*)self);
    if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result];}
    }
    

    //最后,rendercallback
    static OSStatus renderCallback (void *                       inRefCon,
                                AudioUnitRenderActionFlags * ioActionFlags,
                                const AudioTimeStamp *       inTimeStamp,
                                UInt32                       inBusNumber,
                                UInt32                       inNumberFrames,
                                AudioBufferList *            ioData)
    {
    
    OSStatus result;
    if (*ioActionFlags == kAudioUnitRenderAction_PostRender){
        MusicPlayerController* THIS = (__bridge MusicPlayerController *)inRefCon;
    
           result =  ExtAudioFileWriteAsync(THIS->extAudioFileRef, inNumberFrames, ioData);
           if(result) printf("ExtAudioFileWriteAsync %ld \n", result);
    
    }
    return noErr;
    }
    

    最佳答案

    所以我终于解决了这个问题!哎呀,这是一个信息搜集者。

    无论如何,这是我错过的 ExtAudioFile 文档中的一点(请参阅粗体文本)。我没有设置这个属性。数据正在写入我的 .m4a 文件,但在播放时无法读取。总结一下:我有一堆 AUSamplers -> AUMixer -> RemoteIO。 RemoteIO 实例上的渲染回调以压缩的 m4a 格式将数据写入磁盘。因此可以即时生成压缩音频(iOS 5/iPad 2)

    看起来很健壮 - 我在渲染回调中有一些 printf 语句并且写入工作正常。

    耶!


    // specify codec
    UInt32 codec = kAppleHardwareAudioCodecManufacturer;
    size = sizeof(codec);
    result = ExtAudioFileSetProperty(extAudioFileRef,
                                     kExtAudioFileProperty_CodecManufacturer,
                                     size,
                                     &codec);
    
    if(result) printf("ExtAudioFileSetProperty %ld \n", result);
    

    关于ios - 从 RemoteIO : data is getting written but file unplayable 录制到 AAC,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10113977/

    10-09 04:39