Wouter1 / EMU-driver

OSX Kernel extension for Creative Labs EMU driver
189 stars 30 forks source link

restructure audio input code #5

Open Wouter1 opened 9 years ago

Wouter1 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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

Wouter1 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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

Wouter1 commented 9 years ago

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 commented 9 years ago

That USB request block code was cleaned up

Wouter1 commented 9 years ago

EMUUSBAudioEngine::CheckForAssociatedEndpoint is not used. Disabled.

Wouter1 commented 9 years ago

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