Плохая производительность на iPhoneXs/iPhone XS Max при записи звука с использованием аудиоустройства

Я пишу код для аудиозаписи с аудиоустройством, но боюсь, что производительность API аудиоустройства на iPhoneXs/iPhoneXs Max намного хуже, чем на других устройствах iOS, таких как iPhone6s Plus.

Вот некоторые данные о производительности, протестированные с iPhoneXs и iPhone6s Plus для API AudioOutputUnitStart. На самом деле это метод VoiceProcessingAudioUnit:: Start ().

iPhone6s Plus: 150 мс iPhoneXs:500 мс

Я пробовал частоту дискретизации 48 кГц и 16 кГц для аудио сессии, это не имеет значения.

bool VoiceProcessingAudioUnit::Init() {
        //RTC_DCHECK_EQ(state_, kInitRequired);

        // Create an audio component description to identify the Voice Processing
        // I/O audio unit.
        AudioComponentDescription vpio_unit_description;
        vpio_unit_description.componentType = kAudioUnitType_Output;
        vpio_unit_description.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
        vpio_unit_description.componentManufacturer = kAudioUnitManufacturer_Apple;
        vpio_unit_description.componentFlags = 0;
        vpio_unit_description.componentFlagsMask = 0;

        // Obtain an audio unit instance given the description.
        AudioComponent found_vpio_unit_ref =
        AudioComponentFindNext(nullptr, &vpio_unit_description);

        // Create a Voice Processing IO audio unit.
        OSStatus result = noErr;
        result = AudioComponentInstanceNew(found_vpio_unit_ref, &vpio_unit_);
        if (result != noErr) {
            vpio_unit_ = nullptr;

            return false;
        }

        // Enable input on the input scope of the input element.
        UInt32 enable_input = 1;
        result = AudioUnitSetProperty(vpio_unit_, kAudioOutputUnitProperty_EnableIO,
                                      kAudioUnitScope_Input, kInputBus, &enable_input,
                                      sizeof(enable_input));
        if (result != noErr) {
            DisposeAudioUnit();

            return false;
        }

        // Enable output on the output scope of the output element.
        UInt32 enable_output = 0;
        result = AudioUnitSetProperty(vpio_unit_, kAudioOutputUnitProperty_EnableIO,
                                      kAudioUnitScope_Output, kOutputBus,
                                      &enable_output, sizeof(enable_output));
        if (result != noErr) {
            DisposeAudioUnit();

            return false;
        }
//         Specify the callback function that provides audio samples to the audio
//         unit.
        AURenderCallbackStruct render_callback;
        render_callback.inputProc = OnGetPlayoutData;
        render_callback.inputProcRefCon = this;
        result = AudioUnitSetProperty(
                                      vpio_unit_, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
                                      kOutputBus, &render_callback, sizeof(render_callback));
        if (result != noErr) {
            DisposeAudioUnit();
            APM_INFO(@"Failed to specify the render callback on the output bus. "
                        "Error=%ld.",
                        (long)result);
            return false;
        }
        // Disable AU buffer allocation for the recorder, we allocate our own.
        // TODO(henrika): not sure that it actually saves resource to make this call.
        UInt32 flag = 0;
        result = AudioUnitSetProperty(
                                      vpio_unit_, kAudioUnitProperty_ShouldAllocateBuffer,
                                      kAudioUnitScope_Output, kInputBus, &flag, sizeof(flag));
        if (result != noErr) {
            DisposeAudioUnit();

            return false;
        }

        // Specify the callback to be called by the I/O thread to us when input audio
        // is available. The recorded samples can then be obtained by calling the
        // AudioUnitRender() method.
        AURenderCallbackStruct input_callback;
        input_callback.inputProc = OnDeliverRecordedData;
        input_callback.inputProcRefCon = this;
        result = AudioUnitSetProperty(vpio_unit_,
                                      kAudioOutputUnitProperty_SetInputCallback,
                                      kAudioUnitScope_Global, kInputBus,
                                      &input_callback, sizeof(input_callback));
        if (result != noErr) {
            DisposeAudioUnit();

            return false;
        }

        state_ = kUninitialized;
        return true;
    }

bool VoiceProcessingAudioUnit::Initialize(AudioStreamBasicDescription desc){
        AudioStreamBasicDescription format = desc;
        OSStatus result = noErr;
        UInt32 size = sizeof(format);
#if !defined(NDEBUG)
        APMLogStreamDescription(format);
#endif

        // Set the format on the output scope of the input element/bus.
        result =
        AudioUnitSetProperty(vpio_unit_, kAudioUnitProperty_StreamFormat,
                             kAudioUnitScope_Output, kInputBus, &format, size);
        if (result != noErr) {
            return false;
        }


        result = AudioUnitInitialize(vpio_unit_);


        state_ = kInitialized;
        return true;
    }
    bool VoiceProcessingAudioUnit::Initialize(Float64 sample_rate) {
        AudioStreamBasicDescription format = GetFormat(sample_rate);
        return Initialize(format);
    }

    bool VoiceProcessingAudioUnit::Start() {
        OSStatus result = AudioOutputUnitStart(vpio_unit_);

        state_ = kStarted;
        return true;
    }

AudioStreamBasicDescription VoiceProcessingAudioUnit::GetFormat(
                                                                    Float64 sample_rate) const {
        // Set the application formats for input and output:
        // - use same format in both directions
        // - avoid resampling in the I/O unit by using the hardware sample rate
        // - linear PCM => noncompressed audio data format with one frame per packet
        // - no need to specify interleaving since only mono is supported
        AudioStreamBasicDescription format = {0};
        //RTC_DCHECK_EQ(1, kAPMAudioSessionPreferredNumberOfChannels);

        format.mSampleRate = sample_rate;
        format.mFormatID = kAudioFormatLinearPCM;
        format.mFormatFlags =
        kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
        format.mBytesPerPacket = 2;
        format.mFramesPerPacket = 1;  // uncompressed.
        format.mBytesPerFrame = 2;
        format.mChannelsPerFrame = kAPMAudioSessionPreferredNumberOfChannels;
        format.mBitsPerChannel = 8 * 2;
        return format;
    }

//audio session's config
+ (instancetype)asrConfiguration {
    APMAudioSessionConfig *config = [[APMAudioSessionConfig alloc] init];
    config.category = AVAudioSessionCategoryPlayAndRecord;
    config.categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth;
    config.mode = AVAudioSessionModeVoiceChat;
    config.sampleRate =48000;
    config.ioBufferDuration = 0.01;
    config.inputNumberOfChannels = 1;
    config.outputNumberOfChannels = 1;
    return config;

}

Производительность iPhoneXs самого устройства намного выше, чем у iPhone6s plus.so, что делает такую ​​большую разницу в производительности с тем же кодом - это смутило меня.

0 ответов

Другие вопросы по тегам