EMU-driver icon indicating copy to clipboard operation
EMU-driver copied to clipboard

restructure audio input code

Open Wouter1 opened this issue 10 years ago • 14 comments

The current audio input code was coded in the same style as the original code from sourceforge.

That is, all required code is inside the large EMUUSBAudioEngine.

It would be much better if this code could be pulled into the ADRingBuffer class (which was already made but the restructure did not yet materialize). The name ADRingBuffer was picked instead of something like InputRingBuffer because it is only input for the client; for the driver it's also an output buffer.

The USB input stream maybe can be moved to yet another class to keep it separate from the AD ring buffer.

The code around the locking is tricky. It would be nice if this can be done in a cleaner way that link properly to the two requirements for re-use of a USB framelist:

  1. the framelist bytes must have been gathered (GatherInputSamples got all frames from the list)
  2. the completion callback must have been received (readCompleted was called)

Wouter1 avatar Nov 17 '14 21:11 Wouter1

This is a huge amount of work and tricky as well (one error and we have a failing driver). And I can't work on this for long stretches. So I'm doing this in small steps with testing between each commit.

Wouter1 avatar Nov 26 '14 18:11 Wouter1

The plan is to replace also the AD ringbuffer partially with this generic one. I will need to do some performance comparisons before and after replace as I don't have the highly optimized code of the old ringbuffer in the new ringbuffer

In the old ring buffer I see this performance (using Activity Monotor) while sampling stereo @96kHz

HALLab: 1.4% kernel_task: 7.0% (baseline: coreaudiod: 2.1% (baseline:

Wouter1 avatar Nov 28 '14 13:11 Wouter1

In-between CPU load test. Should not make any difference at this point - old ring buffer stil active at this point but we're close to removing I hope

HALLab: 1.4% kernel_task: 7.0% (baseline: coreaudiod: 2.1% (baseline:

identical to previous measurement.

Wouter1 avatar Nov 29 '14 22:11 Wouter1

Something seems broken badly. HALLab still starts up but Audacity hangs up. Really not sure what's going on, I always test these basic things before pushing. I reverted to last version after a panic but it keeps hanging up now. No panics, just hangs. I get this in the console

Nov 30 23:00:11 vlieland kernel[0]: USBF:    264.988    AppleUSBXHCI[0xffffff81a2e95000]::GenerateNextPhysicalSegment - Error generating segments, err: e00002e8, numsegments:1
Nov 30 23:00:11 vlieland kernel[0]: USBF:    264.988    AppleXHCIAsyncEndpoint[0xffffff802f3bae00]::Schedule - returned 0xe00002e8
Nov 30 23:00:11 vlieland kernel[0]: USBF:    264.988    AppleUSBXHCI[0xffffff81a2e95000]::GenerateNextPhysicalSegment - Error generating segments, err: e00002e8, numsegments:1
Nov 30 23:00:11 vlieland kernel[0]: USBF:    264.988    AppleXHCIAsyncEndpoint[0xffffff802f3bae00]::Schedule - returned 0xe00002e8
Nov 30 23:00:11 vlieland kernel[0]: USBF:    264.988    AppleUSBXHCI[0xffffff81a2e95000]::GenerateNextPhysicalSegment - Error generating segments, err: e00002e8, numsegments:1
Nov 30 23:00:11 vlieland kernel[0]: USBF:    264.988    AppleXHCIAsyncEndpoint[0xffffff802f3bae00]::Schedule - returned 0xe00002e8

but that does not help me .

This is the HALLab stack when it hangs (it does not hang anymore, but audacity has similar hang trace)

  15 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12 (CoreFoundation) [0x7fff8449ce0c]
    15 ??? (HALLab + 5388) [0x10cef250c]
      15 ??? (HALLab + 84465) [0x10cf059f1]
        15 ??? (HALLab + 102870) [0x10cf0a1d6]
          15 AudioObjectAddPropertyListener + 129 (CoreAudio) [0x7fff9199905d]
            15 HALSystem::CheckOutInstance() + 159 (CoreAudio) [0x7fff91961759]
              15 HALSystem::InitializeDevices() + 9 (CoreAudio) [0x7fff91963729]
                15 HALPlugInManagement::Initialize() + 324 (CoreAudio) [0x7fff9196387a]
                  15 HALPlugInManagement::CreateHALPlugIn(HALCFPlugIn const*) + 1258 (CoreAudio) [0x7fff91964726]
                    15 HAL_HardwarePlugIn_InitializeWithObjectID(AudioHardwarePlugInInterface**, unsigned int) + 56 (CoreAudio) [0x7fff919654c4]
                      15 HALC_ShellPlugIn::ConnectToServer() + 161 (CoreAudio) [0x7fff91967737]
                        15 HALC_ShellPlugIn::_ReconcileDeviceList(bool, bool) + 759 (CoreAudio) [0x7fff9196c4fb]
                          15 HALC_ProxyObjectMap::CopyObjectByObjectID(unsigned int) + 66 (CoreAudio) [0x7fff919677e0]
                            15 HALC_ProxyObjectMap::_CopyObjectByObjectID(unsigned int) + 240 (CoreAudio) [0x7fff9196798e]
                              15 HALC_ProxyObjectMap::_CreateObject(unsigned int, unsigned int, unsigned int, unsigned int) + 160 (CoreAudio) [0x7fff9196db6a]
                                15 HALC_ProxyObject::HALC_ProxyObject(unsigned int, unsigned int, unsigned int, unsigned int) + 244 (CoreAudio) [0x7fff91967eec]
                                  15 HALC_ProxyObject::HasProperty(AudioObjectPropertyAddress const&, bool&) const + 37 (CoreAudio) [0x7fff9196df8d]
                                    15 HALC_Object_HasProperty + 106 (CoreAudio) [0x7fff9196e00e]
                                      15 mach_msg_trap + 10 (libsystem_kernel.dylib) [0x7fff8ef6fa1a]
                                       *15 ipc_mqueue_receive_continue + 0 (mach_kernel) [0xffffff80002167d0]

Wouter1 avatar Nov 30 '14 22:11 Wouter1

I did nothing, just restarted today, rebuilt, install kext, and started Audacity. It now works all fine again??

Wouter1 avatar Dec 01 '14 17:12 Wouter1

I re-enabled the pop.

Apart from the first "warning. Ignoring overrun", it Audacity runs for 7.5 minutes without any hickup.

Tested another time, 3 minutes. Same, works without any issue.

Wouter1 avatar Dec 01 '14 18:12 Wouter1

Connected convertFromEMUUSBAudioInputStreamNoWrap with the ring buffer. This time, no problem at all!! Previous 2 times the machine panicked immediately

I checked the performance. Notice, at this point the OLD ring is also still fuly working so we are pumping around all USB input bytes through 2 rings

HALLab 0.6 %
kernel_task 0.6%
coreaudiod 3.3%

So coreaudiod is slightly more busy but kernel_task much lower. Not sure why but it looks all fine.

Wouter1 avatar Dec 01 '14 18:12 Wouter1

I had the hanging Audacity again. The problem persisted if I turned off the EMU device briefly. But if I kept it off longer, like 15 seconds, it worked ok again.

Wouter1 avatar Dec 01 '14 20:12 Wouter1

tested again, I really want to be sure it all is ok. Made 9 minute recording. No single hickup or any message during the recording. I think it's good to proceed. Next step will be to take out the old ring buffer and all associated variables with it entirely.

Wouter1 avatar Dec 01 '14 20:12 Wouter1

The code in EMUUSBAudioEngine::performFormatChangeInternal (which I copied from performFormatChange) has lot of duplicate code.

Wouter1 avatar Dec 14 '14 09:12 Wouter1

There is numerous occurrences of code to build a USB request block. All looks like this

    IOReturn        result = kIOReturnError;
    IOUSBDevRequestDesc         devReq;
    IOBufferMemoryDescriptor*   settingDesc = NULL;

    ReturnIf(!mControlInterface, kIOReturnNoDevice);

    settingDesc = IOBufferMemoryDescriptor::withBytes(&newValue, newValueLen, kIODirectionIn,true);
    ReturnIf(!settingDesc, kIOReturnError);

    devReq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
    devReq.bRequest = requestType;
    devReq.wValue =(controlSelector << 8) | channelNumber;
    devReq.wIndex =(0xFF00 &(unitID << 8)) |(0x00FF & mInterfaceNum);
    devReq.wLength = newValueLen;
    devReq.pData = settingDesc;

    debugIOLogC("EMUUSBAudioDevice::setFeatureUnitSetting sending device request %d", requestType);
    if (TRUE != isInactive())   // In case we've been unplugged during sleep
        result = deviceRequest(&devReq);
    debugIOLogC("result= %d.", result);

    settingDesc->release();


    return result;

the only variation seems the data size/name/length.

Wouter1 avatar Dec 21 '14 08:12 Wouter1

That USB request block code was cleaned up

Wouter1 avatar Dec 22 '14 08:12 Wouter1

EMUUSBAudioEngine::CheckForAssociatedEndpoint is not used. Disabled.

Wouter1 avatar Dec 27 '14 13:12 Wouter1

There seems code related to this already in the EMUUSBAudioEngine. Search for aveSampleRateBuf.

Wouter1 avatar Dec 27 '14 13:12 Wouter1