2013-11-18 6 views
1

У меня есть следующая проблема: у меня есть многоканальный микшер (не моя реализация) с использованием AudioToolbox Framework. Я хочу получить значение основного объема на выходе после объединения всех каналов.Возможно ли использовать данные AudioUnit или передавать данные AudioUnit для целей измерения

Любая помощь будет оценена!

EDIT

Я пытаюсь использовать AudioQueueLevelMeterState для возвращения текущего уровня громкости в диапазоне от 0 до 1. Как я прохожу AUGraph или AudioUnit для звуковых сообщений? Может быть, это немного непонятно вопрос, но все-таки ...

-(float)volumeLevel 
{ 
    UInt32 trueValue = true; 
    AudioQueueSetProperty(audioQueue,kAudioQueueProperty_EnableLevelMetering,&trueValue,sizeof (UInt32)); 

    UInt32 dataSize = sizeof(AudioQueueLevelMeterState) * _streamFormat.mChannelsPerFrame; 
    AudioQueueLevelMeterState *level = (AudioQueueLevelMeterState *)malloc(dataSize); 

    float channelAvg = 0; 

    OSStatus rc = AudioQueueGetProperty(audioQueue, kAudioQueueProperty_CurrentLevelMeter, level, &dataSize); 
    if (rc) { 
     NSLog(@"AudioQueueGetProperty(CurrentLevelMeter) returned %d", (int)rc); 
    } else { 
     for (int i = 0; i < _streamFormat.mChannelsPerFrame; i++) { 
      channelAvg += level[i].mPeakPower; 
     } 
    } 
    free(level); 

    printf("Current peak :%f", channelAvg); 
    return channelAvg; 
} 

Здесь фактическая отрезала реализации смесителя:

typedef struct { 
    UInt32    totalFrames; 
    UInt32    nextFrame; 
    UInt32    playedFrames; 
    UInt32    playedLoops; 
    UInt32    activeLoops; 
    Float32    volume; 
    AudioUnitSampleType *dataLeft; 
    AudioUnitSampleType *dataRight; 
} AudioMixerChannel, *AudioMixerChannelPointer; 

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

void audioRouteChangeListenerCallback (void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueSize, const void *inPropertyValue); 

void checkError(OSStatus error, const char *operation); 


@interface AudioMixer() 
{ 
    AudioStreamBasicDescription _streamFormat; 

    AUGraph _graph; 

    AUNode _iONode; 
    AUNode _mixerNode; 

    AudioUnit _mixerUnit; 

    AudioMixerChannel _channels[TRACK_MAX_CHANNELS]; 
} 

@end 

@implementation AudioMixer 

- (id) init 
{ 
    self = [super init]; 

    if (self) { 
     size_t bytesPerSample = sizeof(AudioUnitSampleType); 

     _streamFormat.mFormatID   = kAudioFormatLinearPCM; 
     _streamFormat.mFormatFlags  = kAudioFormatFlagsAudioUnitCanonical; 
     _streamFormat.mBytesPerPacket = (int)bytesPerSample; 
     _streamFormat.mFramesPerPacket = 1; 
     _streamFormat.mBytesPerFrame  = (int)bytesPerSample; 
     _streamFormat.mChannelsPerFrame = 2; 
     _streamFormat.mBitsPerChannel = 8 * (int)bytesPerSample; 
     _streamFormat.mSampleRate  = 44100.0; 


     checkError(NewAUGraph(&_graph), "NewAUGraph"); 
     checkError(AUGraphOpen(_graph), "AUGraphOpen"); 
     checkError(AUGraphInitialize(_graph), "AUGraphInitialize"); 

     AudioComponentDescription iOUnitDescription; 

     iOUnitDescription.componentType   = kAudioUnitType_Output; 
     iOUnitDescription.componentSubType  = kAudioUnitSubType_RemoteIO; 
     iOUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 
     iOUnitDescription.componentFlags   = 0; 
     iOUnitDescription.componentFlagsMask  = 0; 

     checkError(AUGraphAddNode(_graph, &iOUnitDescription, &_iONode), "AUGraphNewNode failed for I/O unit"); 

     AudioComponentDescription MixerUnitDescription; 

     MixerUnitDescription.componentType   = kAudioUnitType_Mixer; 
     MixerUnitDescription.componentSubType  = kAudioUnitSubType_MultiChannelMixer; 
     MixerUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; 
     MixerUnitDescription.componentFlags   = 0; 
     MixerUnitDescription.componentFlagsMask  = 0; 

     checkError(AUGraphAddNode(_graph, &MixerUnitDescription, &_mixerNode), "AUGraphNewNode failed for Mixer unit"); 
     checkError(AUGraphNodeInfo(_graph, _mixerNode, NULL, &_mixerUnit), "AUGraphNodeInfo - mixer unit"); 

     checkError(AUGraphConnectNodeInput(_graph, _mixerNode, 0, _iONode, 0), "AUGraphConnectNodeInput"); 

     for(int i=0; i<TRACK_MAX_CHANNELS; i++) { 
      AURenderCallbackStruct inputCallbackStruct; 

      inputCallbackStruct.inputProc  = &inputRenderCallback; 
      inputCallbackStruct.inputProcRefCon = _channels; 

      checkError(AUGraphSetNodeInputCallback(_graph, _mixerNode, i, &inputCallbackStruct), "AUGraphSetNodeInputCallback"); 
     } 
    } 

    return self; 
} 

ответ

0

Я нашел решение

в первую очередь необходимо, чтобы позволить измерение для каналов микшера:

UInt32 allowMetering = 1; 
    OSStatus status = AudioUnitSetProperty(_mixerUnit, 
              kAudioUnitProperty_MeteringMode, 
              kAudioUnitScope_Output, 
              0, 
              &allowMetering, 
              sizeof(allowMetering)); 

    if (status) { printf("AudioUnitGetParameter kMultiChannelMixerParam_PostAveragePower Input result %ld %08X %4.4s\n", (long)allowMetering, (unsigned int)allowMetering, (char*)&allowMetering); } 

Измерение включено, поэтому мне нужно взять выход объем в шкале дБ:

Float32 value = -120.0; 

OSStatus result = AudioUnitGetParameter(_mixerUnit, 
             kMultiChannelMixerParam_PostAveragePower, 
             kAudioUnitScope_Output, 
             0, 
             &value); 

if (result) { printf("AudioUnitGetParameter kMultiChannelMixerParam_PostAveragePower Input result %ld %08X %4.4s\n", (long)result, (unsigned int)result, (char*)&result); } 

Затем вы можете использовать NSTimer для запуска обновления значения громкости.

 Смежные вопросы

  • Нет связанных вопросов^_^