2016-09-06 1 views
2

iOSプロジェクトで作業中です。マイクロフォンからの入力をキャプチャし、ULaw(データストリームを送信するため)に変換する必要があります。私はこれを達成するためにコンバータノードを備えたAUGraphを使用しています。グラフは正常に作成され、初期化されますが、私のレンダー通知コールバックでは、ioDataバッファにはNULLが含まれていても、inNumberFrameに93の値が含まれていると思われる場合でもNULLを含みます。何が起きているのか。ここAUGraph FormatConverter(AUConverter)レンダリング通知にNULL ioDataバッファが含まれています

コードである:

OSStatus status; 

// ************************** DEFINE AUDIO STREAM FORMATS ****************************** 

double currentSampleRate; 
currentSampleRate = [[AVAudioSession sharedInstance] sampleRate]; 

// Describe stream format 
AudioStreamBasicDescription streamAudioFormat = {0}; 
streamAudioFormat.mSampleRate    = 8000.00; 
streamAudioFormat.mFormatID    = kAudioFormatULaw; 
streamAudioFormat.mFormatFlags   = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; 
streamAudioFormat.mFramesPerPacket  = 1; 
streamAudioFormat.mChannelsPerFrame  = 1; 
streamAudioFormat.mBitsPerChannel   = 8; 
streamAudioFormat.mBytesPerPacket   = 1; 
streamAudioFormat.mBytesPerFrame   = streamAudioFormat.mBytesPerPacket * streamAudioFormat.mFramesPerPacket; 


// ************************** SETUP SEND AUDIO ****************************** 

AUNode ioSendNode; 
AUNode convertToULAWNode; 
AUNode convertToLPCMNode; 
AudioUnit convertToULAWUnit; 
AudioUnit convertToLPCMUnit; 

status = NewAUGraph(&singleChannelSendGraph); 
if (status != noErr) 
{ 
    NSLog(@"Unable to create send audio graph."); 
    return; 
} 

AudioComponentDescription ioDesc = {0}; 
ioDesc.componentType = kAudioUnitType_Output; 
ioDesc.componentSubType = kAudioUnitSubType_VoiceProcessingIO; 
ioDesc.componentManufacturer = kAudioUnitManufacturer_Apple; 
ioDesc.componentFlags = 0; 
ioDesc.componentFlagsMask = 0; 

status = AUGraphAddNode(singleChannelSendGraph, &ioDesc, &ioSendNode); 
if (status != noErr) 
{ 
    NSLog(@"Unable to add IO node."); 
    return; 
} 

AudioComponentDescription converterDesc = {0}; 
converterDesc.componentType = kAudioUnitType_FormatConverter; 
converterDesc.componentSubType = kAudioUnitSubType_AUConverter; 
converterDesc.componentManufacturer = kAudioUnitManufacturer_Apple; 
converterDesc.componentFlags = 0; 
converterDesc.componentFlagsMask = 0; 

status = AUGraphAddNode(singleChannelSendGraph, &converterDesc, &convertToULAWNode); 
if (status != noErr) 
{ 
    NSLog(@"Unable to add ULAW converter node."); 
    return; 
} 

status = AUGraphAddNode(singleChannelSendGraph, &converterDesc, &convertToLPCMNode); 
if (status != noErr) 
{ 
    NSLog(@"Unable to add LPCM converter node."); 
    return; 
} 

status = AUGraphOpen(singleChannelSendGraph); 
if (status != noErr) 
{ 
    return; 
} 

// get the io audio unit 
status = AUGraphNodeInfo(singleChannelSendGraph, ioSendNode, NULL, &ioSendUnit); 
if (status != noErr) 
{ 
    NSLog(@"Unable to get IO unit."); 
    return; 
} 

UInt32 enableInput = 1; 
status = AudioUnitSetProperty (ioSendUnit, 
           kAudioOutputUnitProperty_EnableIO, 
           kAudioUnitScope_Input, 
           1,  // microphone bus 
           &enableInput, 
           sizeof (enableInput) 
           ); 
if (status != noErr) 
{ 
    return; 
} 

UInt32 sizeASBD = sizeof(AudioStreamBasicDescription); 
AudioStreamBasicDescription ioASBDin; 
AudioStreamBasicDescription ioASBDout; 
status = AudioUnitGetProperty(ioSendUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &ioASBDin, &sizeASBD); 
if (status != noErr) 
{ 
    NSLog(@"Unable to get IO stream input format."); 
    return; 
} 

status = AudioUnitGetProperty(ioSendUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &ioASBDout, &sizeASBD); 
if (status != noErr) 
{ 
    NSLog(@"Unable to get IO stream output format."); 
    return; 
} 

ioASBDin.mSampleRate = currentSampleRate; 
ioASBDout.mSampleRate = currentSampleRate; 

status = AudioUnitSetProperty(ioSendUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &ioASBDin, sizeof(ioASBDin)); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set IO stream output format."); 
    return; 
} 

status = AudioUnitSetProperty(ioSendUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &ioASBDin, sizeof(ioASBDin)); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set IO stream input format."); 
    return; 
} 

// get the converter audio unit 
status = AUGraphNodeInfo(singleChannelSendGraph, convertToULAWNode, NULL, &convertToULAWUnit); 
if (status != noErr) 
{ 
    NSLog(@"Unable to get ULAW converter unit."); 
    return; 
} 

status = AudioUnitSetProperty(convertToULAWUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &ioASBDin, sizeof(ioASBDin)); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set ULAW stream input format."); 
    return; 
} 

status = AudioUnitSetProperty(convertToULAWUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamAudioFormat, sizeof(streamAudioFormat)); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set ULAW stream output format."); 
    return; 
} 

// get the converter audio unit 
status = AUGraphNodeInfo(singleChannelSendGraph, convertToLPCMNode, NULL, &convertToLPCMUnit); 
if (status != noErr) 
{ 
    NSLog(@"Unable to get LPCM converter unit."); 
    return; 
} 

status = AudioUnitSetProperty(convertToLPCMUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamAudioFormat, sizeof(streamAudioFormat)); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set LPCM stream input format."); 
    return; 
} 

status = AudioUnitSetProperty(convertToLPCMUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &ioASBDin, sizeof(ioASBDin)); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set LPCM stream output format."); 
    return; 
} 

status = AUGraphConnectNodeInput(singleChannelSendGraph, ioSendNode, 1, convertToULAWNode, 0); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set ULAW node input."); 
    return; 
} 

status = AUGraphConnectNodeInput(singleChannelSendGraph, convertToULAWNode, 0, convertToLPCMNode, 0); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set LPCM node input."); 
    return; 
} 

status = AUGraphConnectNodeInput(singleChannelSendGraph, convertToLPCMNode, 0, ioSendNode, 0); 
if (status != noErr) 
{ 
    NSLog(@"Unable to set IO node input."); 
    return; 
} 

status = AudioUnitAddRenderNotify(convertToULAWUnit, &outputULAWCallback, (__bridge void*)self); 
if (status != noErr) 
{ 
    NSLog(@"Unable to add ULAW render notify."); 
    return; 
} 

status = AUGraphInitialize(singleChannelSendGraph); 
if (status != noErr) 
{ 
    NSLog(@"Unable to initialize send graph."); 
    return; 
} 

CAShow (singleChannelSendGraph); 

}

グラフノードは、次のように初期化される:

Member Nodes: 
node 1: 'auou' 'vpio' 'appl', instance 0x7fd5faf8fac0 O I 
node 2: 'aufc' 'conv' 'appl', instance 0x7fd5fad05420 O I 
node 3: 'aufc' 'conv' 'appl', instance 0x7fd5fad05810 O I 
Connections: 
node 1 bus 1 => node 2 bus 0 [ 1 ch, 44100 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer] 
node 2 bus 0 => node 3 bus 0 [ 1 ch, 8000 Hz, 'ulaw' (0x0000000C) 8 bits/channel, 1 bytes/packet, 1 frames/packet, 1 bytes/frame] 
node 3 bus 0 => node 1 bus 0 [ 1 ch, 44100 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer] 

そして通知レンダリングコールバック:

static OSStatus outputULAWCallback(void *inRefCon, 
          AudioUnitRenderActionFlags *ioActionFlags, 
          const AudioTimeStamp *inTimeStamp, 
          UInt32 inBusNumber, 
          UInt32 inNumberFrames, 
          AudioBufferList *ioData) 
{ 
    AudioManager *audioManager = (__bridge AudioManager*)inRefCon; 
    if ((*ioActionFlags) & kAudioUnitRenderAction_PostRender) 
    { 
     if (!audioManager.mute && ioData->mBuffers[0].mData != NULL) 
     { 
      TPCircularBufferProduceBytes(audioManager.activeChannel == 0 ? audioManager.channel1StreamOutBufferPtr : audioManager.channel2StreamOutBufferPtr, 
            ioData->mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize); 

      // do not want to playback our audio into local speaker 
      SilenceData(ioData); 
     } 
    } 

    return noErr; 
} 

注::マイク入力を出力に直接送信すると(コンバータノードをスキップして)、出力が聞こえるので、AUGraphが機能していることがわかります。

ストリームからULawを受信し、コンバータを通過してスピーカーを再生し、問題なく動作している受信AUGraphセットアップがあります。

コンバータが失敗してデータが返されない理由を理解できません。

誰もこのタイプの問題を経験しましたか?

答えて

1

UPDATE
だから、あなたが他の場所でAUGraphStartを呼んでいるが、ULAWコンバータは、あなたがグラフに別のレートコンバータを追加したり、単にそれを行うにはvpioユニットを得ることができます:(あなたのための一般的なレート変換を行うことを拒否していますあなたのために。

ioASBDin.mSampleRate = currentSampleRate; // change me to 8000Hz 
ioASBDout.mSampleRate = currentSampleRate; // delete me, I'm ignored 

status = AudioUnitSetProperty(ioSendUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &ioASBDin, sizeof(ioASBDin)); 

ioASBDin.mSampleRate = streamAudioFormat.mSampleRate; // a.k.a 8000Hz 

status = AudioUnitSetProperty(ioSendUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &ioASBDin, sizeof(ioASBDin)); 

にこのコードを変更すると、グラフ全体が8kHzの操作を行い作成し、あなたに非ヌルioDataバッファを与えます:

AudioUnitGraph 0xCA51000: 
    Member Nodes: 
    node 1: 'auou' 'vpio' 'appl', instance 0x7b5bb320 O I 
    node 2: 'aufc' 'conv' 'appl', instance 0x7c878d50 O I 
    node 3: 'aufc' 'conv' 'appl', instance 0x7c875eb0 O I 
Connections: 
    node 1 bus 1 => node 2 bus 0 [ 1 ch, 8000 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer] 
    node 2 bus 0 => node 3 bus 0 [ 1 ch, 8000 Hz, 'ulaw' (0x0000000C) 8 bits/channel, 1 bytes/packet, 1 frames/packet, 1 bytes/frame] 
    node 3 bus 0 => node 1 bus 0 [ 1 ch, 8000 Hz, 'lpcm' (0x0000000C) 16-bit little-endian signed integer] 
CurrentState: 
    mLastUpdateError=0, eventsToProcess=F, isInitialized=T, isRunning=T (1) 

古い答えはあなたが

  1. AUGraphStartあなたのグラフに必要

  2. mSampleRateから11025、22050または

44100そしてあなたULAWを変更

  • 必要になります非ヌルを参照kAudioUnitRenderAction_PostRender段階のlioDataです。

    8kHzまたは16kHzのulawに変換することは、オーディオコンバータが行うことができるもののようです。なぜ動作しないのかわかりませんが、サンプルレートをポイント2の値以外に設定すると、ulawコンバータはkAUGraphErr_CannotDoInCurrentContext(-10863)というエラーを報告します。これは意味をなさないものです。

  • +0

    AUGraphStartの呼び出しがコードの別の部分で実行されていたため、グラフが実行されていました。明らかに、私は8kHzに変換する必要があるので、他のものに変更することはできません。 – DRourke

    +0

    明らかに相対的です。更新された答えを確認してください。 –

    +0

    vpioユニットのサンプルレートを8KHzに変更すると機能します。あなたはconvユニットが使用しているのと同じ変換ロジックを使用していると思うでしょうが、何かが異なっていなければなりません。ご協力いただきありがとうございます! – DRourke

    関連する問題