gpt4 book ai didi

ios - 从 RemoteIO : data is getting written but file unplayable 录制到 AAC

转载 作者:可可西里 更新时间:2023-11-01 03:27:29 27 4
gpt4 key购买 nike

我一直在尝试在 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 黑暗水域的人。


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

enter image description here

//remoteIO设置的一部分

    // 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));

//设置文件和 rendercallback 的函数

 - (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];}
}

//最后,渲染回调

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)

看起来非常稳健——我在 rendercallback 中有一些 printf 语句并且写入工作正常。

耶!

ExtAudioFileProperty_CodecManufacturer The manufacturer of the codec to be used by the extended audio file object. Value is a read/write UInt32. You must specify this property before setting the kExtAudioFileProperty_ClientDataFormat (page 20) property, which in turn triggers the creation of the codec. Use this property in iOS to choose between a hardware or software encoder, by specifying kAppleHardwareAudioCodecManufacturer or kAppleSoftwareAudioCodecManufacturer. Available in Mac OS X v10.7 and later. Declared in ExtendedAudioFile.h.

// 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com