Ken Thomases : winecoreaudio: Add AudioUnit_CreateInputUnit to create an input audio unit.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Dec 29 06:47:17 CST 2006


Module: wine
Branch: master
Commit: 30a1b293516d03457a98b8758c3bee5e38052de1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=30a1b293516d03457a98b8758c3bee5e38052de1

Author: Ken Thomases <ken at codeweavers.com>
Date:   Thu Dec 28 11:05:24 2006 -0600

winecoreaudio: Add AudioUnit_CreateInputUnit to create an input audio unit.

---

 dlls/winmm/winecoreaudio/audiounit.c |  133 ++++++++++++++++++++++++++++++++++
 1 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/dlls/winmm/winecoreaudio/audiounit.c b/dlls/winmm/winecoreaudio/audiounit.c
index fe1c7ec..03b4d00 100644
--- a/dlls/winmm/winecoreaudio/audiounit.c
+++ b/dlls/winmm/winecoreaudio/audiounit.c
@@ -33,6 +33,13 @@ extern OSStatus CoreAudio_woAudioUnitIOP
 				UInt32 inNumberFrames, 
 				AudioBufferList *ioData);
 
+extern OSStatus CoreAudio_wiAudioUnitIOProc(void *inRefCon,
+				AudioUnitRenderActionFlags *ioActionFlags,
+				const AudioTimeStamp *inTimeStamp,
+				UInt32 inBusNumber,
+				UInt32 inNumberFrames,
+				AudioBufferList *ioData);
+
 int AudioUnit_CreateDefaultAudioUnit(void *wwo, AudioUnit *au)
 {
     OSStatus err;
@@ -121,4 +128,130 @@ int AudioUnit_GetVolume(AudioUnit au, fl
     *right = *left;
     return 1;
 }
+
+
+int AudioUnit_CreateInputUnit(void* wwi, AudioUnit* out_au,
+        WORD nChannels, DWORD nSamplesPerSec, WORD wBitsPerSample)
+{
+    OSStatus                    err = noErr;
+    ComponentDescription        description;
+    Component                   component;
+    AudioUnit                   au;
+    UInt32                      param;
+    AURenderCallbackStruct      callback;
+    AudioDeviceID               defaultInputDevice;
+    AudioStreamBasicDescription desiredFormat;
+
+
+    /* Open the AudioOutputUnit */
+    description.componentType           = kAudioUnitType_Output;
+    description.componentSubType        = kAudioUnitSubType_HALOutput;
+    description.componentManufacturer   = kAudioUnitManufacturer_Apple;
+    description.componentFlags          = 0;
+    description.componentFlagsMask      = 0;
+
+    component = FindNextComponent(NULL, &description);
+    if (!component)
+    {
+        ERR("FindNextComponent(kAudioUnitSubType_HALOutput) failed\n");
+        return 0;
+    }
+
+    err = OpenAComponent(component, &au);
+    if (err != noErr || au == NULL)
+    {
+        ERR("OpenAComponent failed: %08lx\n", err);
+        return 0;
+    }
+
+    /* Configure the AudioOutputUnit */
+    /* The AUHAL has two buses (AKA elements).  Bus 0 is output from the app
+     * to the device.  Bus 1 is input from the device to the app.  Each bus
+     * has two ends (AKA scopes).  Data goes from the input scope to the
+     * output scope.  The terminology is somewhat confusing because the terms
+     * "input" and "output" have two meanings.  Here's a summary:
+     *
+     *      Bus 0, input scope: refers to the source of data to be output as sound
+     *      Bus 0, output scope: refers to the actual sound output device
+     *      Bus 1, input scope: refers to the actual sound input device
+     *      Bus 1, output scope: refers to the destination of data received by the input device
+     */
+
+    /* Enable input on the AUHAL */
+    param = 1;
+    err = AudioUnitSetProperty(au, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &param, sizeof(param));
+    if (err != noErr)
+    {
+        ERR("Couldn't enable input on AUHAL: %08lx\n", err);
+        goto error;
+    }
+
+    /* Disable Output on the AUHAL */
+    param = 0;
+    err = AudioUnitSetProperty(au, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &param, sizeof(param));
+    if (err != noErr)
+    {
+        ERR("Couldn't disable output on AUHAL: %08lx\n", err);
+        goto error;
+    }
+
+    /* Find the default input device */
+    param = sizeof(defaultInputDevice);
+    err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &param, &defaultInputDevice);
+    if (err != noErr || defaultInputDevice == kAudioDeviceUnknown)
+    {
+        ERR("Couldn't get the default audio device ID: %08lx\n", err);
+        goto error;
+    }
+
+    /* Set the current device to the default input device. */
+    err = AudioUnitSetProperty(au, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &defaultInputDevice, sizeof(defaultInputDevice));
+    if (err != noErr)
+    {
+        ERR("Couldn't set current device of AUHAL to default input device: %08lx\n", err);
+        goto error;
+    }
+
+    /* Setup render callback */
+    /* This will be called when the AUHAL has input data.  However, it won't
+     * be passed the data itself.  The callback will have to all AudioUnitRender. */
+    callback.inputProc = CoreAudio_wiAudioUnitIOProc;
+    callback.inputProcRefCon = wwi;
+    err = AudioUnitSetProperty(au, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback));
+    if (err != noErr)
+    {
+        ERR("Couldn't set input callback of AUHAL: %08lx\n", err);
+        goto error;
+    }
+
+    /* Setup the desired data format. */
+    desiredFormat.mFormatID         = kAudioFormatLinearPCM;
+    desiredFormat.mFormatFlags      = kLinearPCMFormatFlagIsPacked;
+    if (wBitsPerSample != 8)
+        desiredFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
+    desiredFormat.mSampleRate       = nSamplesPerSec;
+    desiredFormat.mChannelsPerFrame = nChannels;
+    desiredFormat.mFramesPerPacket  = 1;
+    desiredFormat.mBitsPerChannel   = wBitsPerSample;
+    desiredFormat.mBytesPerFrame    = desiredFormat.mBitsPerChannel * desiredFormat.mChannelsPerFrame / 8;
+    desiredFormat.mBytesPerPacket   = desiredFormat.mBytesPerFrame * desiredFormat.mFramesPerPacket;
+
+    /* Set the AudioOutputUnit output data format */
+    err = AudioUnitSetProperty(au, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &desiredFormat, sizeof(desiredFormat));
+    if (err != noErr)
+    {
+        ERR("Couldn't set desired input format of AUHAL: %08lx\n", err);
+        goto error;
+    }
+
+    *out_au = au;
+
+    return 1;
+
+error:
+    if (au)
+        CloseComponent(au);
+    return 0;
+}
+
 #endif




More information about the wine-cvs mailing list