示例#1
0
CoreAudioDriver::CoreAudioDriver( audioProcessCallback processCallback )
		: H2Core::AudioOutput( __class_name )
		, m_bIsRunning( false )
		, mProcessCallback( processCallback )
		, m_pOut_L( NULL )
		, m_pOut_R( NULL )
{
	//INFOLOG( "INIT" );
	m_nSampleRate = Preferences::get_instance()->m_nSampleRate;

	//Get the default playback device and store it in m_outputDevice
	retrieveDefaultDevice();

	//Get the buffer size of the previously detected device and store it in m_nBufferSize
	retrieveBufferSize();

	// print some info
	printStreamInfo();
}
/* initialize default sound device */
boolean adin_mic_standby(int sfreq, void* dummy) {
    OSStatus status;
    UInt32 propertySize;
    struct AudioStreamBasicDescription inDesc;
    int err;

    jlog("Stat: adin_darwin: sample rate = %d\n", sfreq);

    if (CoreAudioInit)
        return TRUE;

#ifdef MAC_OS_X_VERSION_10_6
    AudioComponent halout;
    AudioComponentDescription haloutDesc;
#else
    Component halout;
    ComponentDescription haloutDesc;
#endif

    haloutDesc.componentType = kAudioUnitType_Output;
    haloutDesc.componentSubType = kAudioUnitSubType_HALOutput;
    haloutDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
    haloutDesc.componentFlags = 0;
    haloutDesc.componentFlagsMask = 0;
    halout = FindNextComponent(NULL, &haloutDesc);

    if(halout == NULL) {
        jlog("Error: adin_darwin: no HALOutput component found\n");
        return FALSE;
    }

    OpenAComponent(halout, &InputUnit);

    UInt32 enableIO;

    enableIO = 1;
    status = AudioUnitSetProperty(InputUnit,
                                  kAudioOutputUnitProperty_EnableIO,
                                  kAudioUnitScope_Input,
                                  1,
                                  &enableIO,
                                  sizeof(enableIO));
    if (status != noErr) {
        jlog("Error: adin_darwin: cannot set InputUnit's EnableIO(Input)\n");
        return FALSE;
    }

    enableIO = 0;
    status = AudioUnitSetProperty(InputUnit,
                                  kAudioOutputUnitProperty_EnableIO,
                                  kAudioUnitScope_Output,
                                  0,
                                  &enableIO,
                                  sizeof(enableIO));
    if (status != noErr) {
        jlog("Error: adin_darwin: cannot set InputUnit's EnableIO(Output)\n");
        return FALSE;
    }


    /* get default input device */
    propertySize = sizeof(InputDeviceID);
    status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
                                      &propertySize,
                                      &InputDeviceID);
    if (status != noErr) {
        jlog("Error: adin_darwin: cannot get default input device\n");
        return FALSE;
    }

    if (InputDeviceID == kAudioDeviceUnknown) {
        jlog("Error: adin_darwin: no available input device found\n");
        return FALSE;

    } else {

        CoreAudioHasInputDevice = TRUE;

        /* get input device name */
        propertySize = sizeof(char) * DEVICE_NAME_LEN;
        status = AudioDeviceGetProperty(InputDeviceID,
                                        1,
                                        1,
                                        kAudioDevicePropertyDeviceName,
                                        &propertySize,
                                        deviceName);
        if (status != noErr) {
            jlog("Error: adin_darwin: cannot get device name\n");
            return FALSE;
        }

        status = AudioUnitSetProperty(InputUnit,
                                      kAudioOutputUnitProperty_CurrentDevice,
                                      kAudioUnitScope_Global,
                                      0,
                                      &InputDeviceID,
                                      sizeof(InputDeviceID));

        if (status != noErr) {
            jlog("Error: adin_darwin: cannot bind default input device to AudioUnit\n");
            return FALSE;
        }

        /* get input device's format */
        propertySize = sizeof(inDesc);
        status = AudioDeviceGetProperty(InputDeviceID,
                                        1,
                                        1,
                                        kAudioDevicePropertyStreamFormat,
                                        &propertySize,
                                        &inDesc);
        if (status != noErr) {
            jlog("Error: adin_darwin: cannot get input device's stream format\n");
            return FALSE;
        }

        /* get input device's buffer frame size */
        UInt32 bufferFrameSize;
        propertySize = sizeof(bufferFrameSize);
        status = AudioDeviceGetProperty(InputDeviceID,
                                        1,
                                        1,
                                        kAudioDevicePropertyBufferFrameSize,
                                        &propertySize,
                                        &bufferFrameSize);
        if (status != noErr) {
            jlog("Error: adin_darwin: cannot get input device's buffer frame size\n");
            return FALSE;
        }

        jlog("Stat: adin_darwin: using device \"%s\" for input\n", deviceName);
        jlog("Stat: adin_darwin: sample rate %f\n\t%ld channels\n\t%ld-bit sample\n",
             inDesc.mSampleRate,
             inDesc.mChannelsPerFrame,
             inDesc.mBitsPerChannel);

        jlog("Stat: adin_darwin: %d buffer frames\n", bufferFrameSize);


        printStreamInfo(&inDesc);

        UInt32 formatFlagEndian =
            inDesc.mFormatFlags & kAudioFormatFlagIsBigEndian;

        inDesc.mFormatFlags =
            kAudioFormatFlagIsSignedInteger |
            kAudioFormatFlagIsPacked |
            formatFlagEndian;

        inDesc.mBytesPerPacket = BytesPerSample;
        inDesc.mFramesPerPacket = 1;
        inDesc.mBytesPerFrame = BytesPerSample;
        inDesc.mChannelsPerFrame = 1;
        inDesc.mBitsPerChannel = BytesPerSample * BITS_PER_BYTE;

        printStreamInfo(&inDesc);

        propertySize = sizeof(inDesc);
        status = AudioUnitSetProperty(InputUnit,
                                      kAudioUnitProperty_StreamFormat,
                                      kAudioUnitScope_Output,
                                      1,
                                      &inDesc,
                                      propertySize
                                     );
        if (status != noErr) {
            jlog("Error: adin_darwin: cannot set InputUnit's stream format\n");
            return FALSE;
        }

        InputBytesPerPacket = inDesc.mBytesPerPacket;
        InputFramesPerPacket = inDesc.mFramesPerPacket;
        InputSamplesPerPacket = InputBytesPerPacket / BytesPerSample;

        InputDeviceBufferSamples =
            bufferFrameSize * InputSamplesPerPacket * InputFramesPerPacket;

        jlog("Stat: adin_darwin: input device's buffer size (# of samples): %d\n",
             InputDeviceBufferSamples);

        AudioStreamBasicDescription outDesc;
        outDesc.mSampleRate = sfreq;
        outDesc.mFormatID = kAudioFormatLinearPCM;
        outDesc.mFormatFlags =
            kAudioFormatFlagIsSignedInteger |
            kAudioFormatFlagIsPacked |
            formatFlagEndian;
        outDesc.mBytesPerPacket = BytesPerSample;
        outDesc.mFramesPerPacket = 1;
        outDesc.mBytesPerFrame = BytesPerSample;
        outDesc.mChannelsPerFrame = 1;
        outDesc.mBitsPerChannel = BytesPerSample * BITS_PER_BYTE;

        printStreamInfo(&outDesc);

        OutputBitsPerChannel = outDesc.mBitsPerChannel;
        OutputBytesPerPacket = outDesc.mBytesPerPacket;

        OutputSamplesPerPacket = (OutputBitsPerChannel / BITS_PER_BYTE) / OutputBytesPerPacket;

        status = AudioConverterNew(&inDesc, &outDesc, &Converter);
        if (status != noErr) {
            jlog("Error: adin_darwin: cannot create audio converter\n");
            return FALSE;
        }

        /*
        UInt32 nChan = inDesc.mChannelsPerFrame;
        int i;

        if (inDesc.mFormatFlags & kAudioFormatFlagIsNonInterleaved && nChan > 1) {
          UInt32 chmap[nChan];
          for (i = 0; i < nChan; i++)
        chmap[i] = 0;

          status = AudioConverterSetProperty(Converter,
        				 kAudioConverterChannelMap,
        				 sizeof(chmap), chmap);
          if (status != noErr){
        jlog("cannot set audio converter's channel map\n");
        return FALSE;
          }
        }
        */

        status =
            AudioConverterSetProperty(Converter,
                                      kAudioConverterSampleRateConverterQuality,
                                      sizeof(ConvQuality), &ConvQuality);
        if (status != noErr) {
            jlog("Error: adin_darwin: cannot set audio converter quality\n");
            return FALSE;
        }


        //jlog("Stat: adin_darwin: audio converter generated\n");

        /* allocate buffers */
        BufList = allocateAudioBufferList(inDesc.mBitsPerChannel / BITS_PER_BYTE,
                                          InputDeviceBufferSamples, 1);
        if (BufList == NULL) return FALSE;

        BufListBackup.mNumberBuffers = BufList->mNumberBuffers;

        BufListBackup.mBuffers[0].mNumberChannels = 1;
        BufListBackup.mBuffers[0].mDataByteSize =
            BufList->mBuffers[0].mDataByteSize;
        BufListBackup.mBuffers[0].mData = BufList->mBuffers[0].mData;

        BufListConverted = allocateAudioBufferList(BytesPerSample, BUF_SAMPLES, 1);
        if (BufListConverted == NULL) return FALSE;
        //jlog("Stat: adin_darwin: buffers allocated\n");

        err = pthread_mutex_init(&MutexInput, NULL);
        if (err) {
            jlog("Error: adin_darwin: cannot init mutex\n");
            return FALSE;
        }
        err = pthread_cond_init(&CondInput, NULL);
        if (err) {
            jlog("Error: adin_darwin: cannot init condition variable\n");
            return FALSE;
        }

        /* register the callback */
        AURenderCallbackStruct input;
        input.inputProc = InputProc; // an AURenderCallback
        input.inputProcRefCon = 0;
        AudioUnitSetProperty(InputUnit,
                             kAudioOutputUnitProperty_SetInputCallback,
                             kAudioUnitScope_Global,
                             0,
                             &input,
                             sizeof(input));

        status = AudioUnitInitialize(InputUnit);
        if (status != noErr) {
            jlog("Error: adin_darwin: InputUnit initialize failed\n");
            return FALSE;
        }

    }

    CoreAudioInit = TRUE;

    jlog("Stat: adin_darwin: CoreAudio: initialized\n");

    return TRUE;
}