【问题标题】:record sounds played by my iPhone app with audio units使用音频单元录制我的 iPhone 应用程序播放的声音
【发布时间】:2011-10-25 08:06:35
【问题描述】:

我今天收集了很多关于 iOS 和音频单元 的有趣内容,并且发现了很多有用的资源(包括在内)。

首先,我很困惑:真的有必要用 mixer unit 创建一个 audio graph 来记录播放的声音吗通过应用程序?

或者使用ObjectAL(或更简单的 AVAudioPlayer 调用)播放声音并使用录音回调在正确的总线上创建一个单独的远程 io 单元就足够了吗?

第二个,一个更加程序化的问题! 由于我对 Audio Units 的概念还不是很满意,因此我尝试使用 apple Mixer Host project 来录制混音结果。显然,我尝试使用Michael Tyson RemoteIO post 来做到这一点。

我在我的回调函数上得到一个 EXC_BAD_ACCESS :

static OSStatus recordingCallback       (void *inRefCon,
                                  AudioUnitRenderActionFlags *ioActionFlags,
                                  const AudioTimeStamp *inTimeStamp,
                                  UInt32        inBusNumber,
                                  UInt32        inNumberFrames,
                                  AudioBufferList *ioData) {

    AudioBufferList *bufferList; // <- Fill this up with buffers (you will want to malloc it, as it's a dynamic-length list)

    EffectState *effectState = (EffectState *)inRefCon;
    AudioUnit rioUnit = effectState->rioUnit;

    OSStatus status;

    // BELOW I GET THE ERROR
    status = AudioUnitRender(rioUnit,      
                             ioActionFlags, 
                             inTimeStamp, 
                             inBusNumber, 
                             inNumberFrames, 
                             bufferList);

    if (noErr != status) { NSLog(@"AudioUnitRender error"); return noErr;}

    // Now, we have the samples we just read sitting in buffers in bufferList
    //ExtAudioFileWriteAsync(effectState->audioFileRef, inNumberFrames, bufferList);

    return noErr;
}

在使用回调函数之前,我在 MixerHostAudio.h

typedef struct {
    AudioUnit rioUnit;
    ExtAudioFileRef audioFileRef;
} EffectState;

并在界面中创建:

AudioUnit                       iOUnit;
EffectState effectState;
AudioStreamBasicDescription     iOStreamFormat;
...
@property                       AudioUnit           iOUnit;
@property (readwrite)           AudioStreamBasicDescription iOStreamFormat;

然后在实现文件MixerHostAudio.h中:

#define kOutputBus 0
#define kInputBus 1
...
@synthesize iOUnit;                    // the Remote IO unit
...
result =    AUGraphNodeInfo (
                             processingGraph,
                             iONode,
                             NULL,
                             &iOUnit
                             );

if (noErr != result) {[self printErrorMessage: @"AUGraphNodeInfo" withStatus: result]; return;}

// Enable IO for recording
UInt32 flag = 1;
result = AudioUnitSetProperty(iOUnit, 
                              kAudioOutputUnitProperty_EnableIO, 
                              kAudioUnitScope_Input, 
                              kInputBus,
                              &flag, 
                              sizeof(flag));

if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}
// Describe format
iOStreamFormat.mSampleRate          = 44100.00;
iOStreamFormat.mFormatID            = kAudioFormatLinearPCM;
iOStreamFormat.mFormatFlags     = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
iOStreamFormat.mFramesPerPacket = 1;
iOStreamFormat.mChannelsPerFrame    = 1;
iOStreamFormat.mBitsPerChannel      = 16;
iOStreamFormat.mBytesPerPacket      = 2;
iOStreamFormat.mBytesPerFrame       = 2;

// Apply format
result = AudioUnitSetProperty(iOUnit, 
                              kAudioUnitProperty_StreamFormat, 
                              kAudioUnitScope_Output, 
                              kInputBus, 
                              &iOStreamFormat, 
                              sizeof(iOStreamFormat));

if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}

result = AudioUnitSetProperty(iOUnit, 
                              kAudioUnitProperty_StreamFormat, 
                              kAudioUnitScope_Input, 
                              kOutputBus, 
                              &iOStreamFormat, 
                              sizeof(iOStreamFormat));

if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}

effectState.rioUnit = iOUnit;

// Set input callback ----> RECORDING
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = recordingCallback;
callbackStruct.inputProcRefCon = self;
result = AudioUnitSetProperty(iOUnit, 
                              kAudioOutputUnitProperty_SetInputCallback, 
                              kAudioUnitScope_Global, 
                              kInputBus, 
                              &callbackStruct, 
                              sizeof(callbackStruct));

if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}

但我不知道出了什么问题,也不知道如何挖掘。 注意:存在 EffectState 结构是因为我还尝试集成 BioAudio project 从缓冲区写入文件的能力。

第三个,我想知道是否有更简单的方法来录制我的 iPhone 应用程序播放的声音(即不包括麦克风)?

【问题讨论】:

  • 它对你有用吗????录制音频文件,,,,
  • 对不起,这不是我想要的,我想混合两个音频文件并将其保存在另一个音频文件中,你知道吗???
  • 在如何录制您的应用播放的声音方面有什么进展吗?这似乎是一个在互联网上很少被问到的问题!

标签: ios audio audio-recording audiounit


【解决方案1】:

我自己发现的。我忘了像这样链接:

callbackStruct.inputProcRefCon = &effectState;

这是代码部分。现在我又遇到了概念问题...

【讨论】:

  • 能否分享整个文件以录制输出音频?
  • 嗨@Hardik1344,很抱歉,我无法再访问源代码。
  • 没问题,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多