I modified pa_mac_core.c (4/12/02 version) in portaudio (V18) to get full-duplex using USB iMic on pd.
Although one can get full-duplex using Built-in audio because it appears as one CoreAudio device, iMic, for example, is mapped to two CoreAudio devices.
Main modifications:
Start (and stop) a second IOProc when there are two different CoreAudio devices. (Even two different physical devices, I can get input from iMic and output on Built-in speakers.)
In the IOProc (actually Pa_TimeSlice) use mNumberBuffers instead of past_NumOutputChannels to determine if this is for output or input.
Note: it's tested only with iMic and pd-0.35-test23 (G4 laptop).
The diff file is provided below (patch pa_mac_core.c diff).
Ich
================================================= Ichiro Fujinaga (ich@jhu.edu) Computer Music Department Peabody Institute of the Johns Hopkins University 1 E. Mount Vernon Place, Baltimore MD USA 21202 Voice: (410) 659-8100 x1240 Fax: (410) 783-8592 http://www.peabody.jhu.edu/~ich =================================================
656c656,657
// if( past->past_NumOutputChannels > 0 ) IF if( outOutputData->mNumberBuffers > 0 )
662c663,664
// if( past->past_NumInputChannels > 0 ) IF if( inInputData->mNumberBuffers > 0 )
668a671
712c715
//printf("Num input Buffers: %d; Num output Buffers: %d.\n", inInputData->mNumberBuffers, outOutputData->mNumberBuffers);
974a978
#if 0 // checking diabled IF
987c991
#endif
1050a1055,1070
// IF start - code added if (pahsc->pahsc_AudioDeviceID != sDeviceInfos[past->past_OutputDeviceID].audioDeviceID) {
AudioDeviceID outputDeviceID = sDeviceInfos[past->past_OutputDeviceID].audioDeviceID; // Assumes output device since pahsc->pahsc_AudioDeviceID is set as inputdevice last in PaHost_OpenStream()// Associate an IO proc with the device and pass a pointer to the audio data context err = AudioDeviceAddIOProc(outputDeviceID, (AudioDeviceIOProc)appIOProc, past); if (err != noErr) goto error; // start playing sound through the device err = AudioDeviceStart(outputDeviceID, (AudioDeviceIOProc)appIOProc); if (err != noErr) goto error; }
// IF end
1085a1106,1115
if (pahsc->pahsc_AudioDeviceID != sDeviceInfos[past->past_OutputDeviceID].audioDeviceID) { // stop if second IOProc was started IF AudioDeviceID outputDeviceID = sDeviceInfos[past->past_OutputDeviceID].audioDeviceID; // FIXME - we should ask proc to stop instead of stopping abruptly err = AudioDeviceStop(outputDeviceID, (AudioDeviceIOProc)appIOProc); if (err != noErr) goto Bail; err = AudioDeviceRemoveIOProc(outputDeviceID, (AudioDeviceIOProc)appIOProc); if (err != noErr) goto Bail; }