git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3922 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
| @@ -1,314 +0,0 @@ | |||||
| /* | |||||
| Copyright (C) 2009 Grame | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| */ | |||||
| #include "JackAudioQueueAdapter.h" | |||||
| //#include <CoreServices/CoreServices.h> | |||||
| namespace Jack | |||||
| { | |||||
| // NOT YET WORKING.... | |||||
| static void Print4CharCode(const char* msg, long c) | |||||
| { | |||||
| UInt32 __4CC_number = (c); | |||||
| char __4CC_string[5]; | |||||
| //*((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number); | |||||
| __4CC_string[4] = 0; | |||||
| //printf("%s'%s'\n", (msg), __4CC_string); | |||||
| snprintf(__4CC_string, 5, "%s'%s'\n", (msg), __4CC_string); | |||||
| } | |||||
| static int ComputeRecordBufferSize(AudioQueueRef mQueue, const AudioStreamBasicDescription *format, float seconds) | |||||
| { | |||||
| OSStatus err; | |||||
| int packets, frames, bytes = 0; | |||||
| frames = (int)ceil(seconds * format->mSampleRate); | |||||
| if (format->mBytesPerFrame > 0) | |||||
| bytes = frames * format->mBytesPerFrame; | |||||
| else { | |||||
| UInt32 maxPacketSize; | |||||
| if (format->mBytesPerPacket > 0) { | |||||
| maxPacketSize = format->mBytesPerPacket; // constant packet size | |||||
| } else { | |||||
| UInt32 propertySize = sizeof(maxPacketSize); | |||||
| if ((err = AudioQueueGetProperty(mQueue, kAudioQueueProperty_MaximumOutputPacketSize, &maxPacketSize, &propertySize)) != noErr) { | |||||
| printf("Couldn't get queue's maximum output packet size\n"); | |||||
| return 0; | |||||
| } | |||||
| } | |||||
| if (format->mFramesPerPacket > 0) | |||||
| packets = frames / format->mFramesPerPacket; | |||||
| else | |||||
| packets = frames; // worst-case scenario: 1 frame in a packet | |||||
| if (packets == 0) // sanity check | |||||
| packets = 1; | |||||
| bytes = packets * maxPacketSize; | |||||
| } | |||||
| return bytes; | |||||
| } | |||||
| void JackAudioQueueAdapter::CaptureCallback(void * inUserData, | |||||
| AudioQueueRef inAQ, | |||||
| AudioQueueBufferRef inBuffer, | |||||
| const AudioTimeStamp * inStartTime, | |||||
| UInt32 inNumPackets, | |||||
| const AudioStreamPacketDescription *inPacketDesc) | |||||
| { | |||||
| JackAudioQueueAdapter* adapter = (JackAudioQueueAdapter*)inUserData; | |||||
| OSStatus err; | |||||
| printf("JackAudioQueueAdapter::CaptureCallback\n"); | |||||
| // Use the adapter to communicate with audio callback | |||||
| // jack_adapter_push_input(adapter, audio_output, audio_output_buffer); | |||||
| if ((err = AudioQueueEnqueueBuffer(adapter->fCaptureQueue, inBuffer, 0, NULL)) != noErr) { | |||||
| printf("JackAudioQueueAdapter::CaptureCallback error %d\n", err); | |||||
| } else { | |||||
| printf("JackAudioQueueAdapter::CaptureCallback enqueue buffer\n"); | |||||
| } | |||||
| } | |||||
| void JackAudioQueueAdapter::PlaybackCallback(void * inUserData, | |||||
| AudioQueueRef inAQ, | |||||
| AudioQueueBufferRef inCompleteAQBuffer) | |||||
| { | |||||
| JackAudioQueueAdapter* adapter = (JackAudioQueueAdapter*)inUserData; | |||||
| OSStatus err; | |||||
| printf("JackAudioQueueAdapter::PlaybackCallback\n"); | |||||
| // Use the adapter to communicate with audio callback | |||||
| // jack_adapter_pull_output(adapter, audio_input, audio_input_buffer); | |||||
| //if (AudioQueueEnqueueBuffer(adapter->fPlaybackQueue, inCompleteAQBuffer, 0, &adapter->fPlaybackPacketDescs) != noErr) { | |||||
| if ((err = AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, 0, NULL)) != noErr) { | |||||
| printf("JackAudioQueueAdapter::PlaybackCallback error %d\n", err); | |||||
| } else { | |||||
| printf("JackAudioQueueAdapter::PlaybackCallback enqueue buffer\n"); | |||||
| } | |||||
| } | |||||
| void JackAudioQueueAdapter::InterruptionListener(void* inClientData, UInt32 inInterruptionState) | |||||
| { | |||||
| JackAudioQueueAdapter* obj = (JackAudioQueueAdapter*)inClientData; | |||||
| } | |||||
| void JackAudioQueueAdapter::PropListener(void* inClientData, | |||||
| AudioSessionPropertyID inID, | |||||
| UInt32 inDataSize, | |||||
| const void* inData) | |||||
| {} | |||||
| JackAudioQueueAdapter::JackAudioQueueAdapter(int inchan, int outchan, jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_adapter_t* adapter) | |||||
| :fCaptureChannels(inchan), fPlaybackChannels(outchan), fBufferSize(buffer_size), fSampleRate(sample_rate), fAdapter(adapter) | |||||
| {} | |||||
| JackAudioQueueAdapter::~JackAudioQueueAdapter() | |||||
| {} | |||||
| int JackAudioQueueAdapter::Open() | |||||
| { | |||||
| OSStatus err; | |||||
| int bufferByteSize; | |||||
| UInt32 size; | |||||
| /* | |||||
| err = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); | |||||
| if (err != noErr) { | |||||
| fprintf(stderr, "AudioSessionInitialize error %d\n", err); | |||||
| return -1; | |||||
| } | |||||
| err = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, PropListener, this); | |||||
| if (err) { | |||||
| fprintf(stderr, "kAudioSessionProperty_AudioRouteChange error %d\n", err); | |||||
| } | |||||
| UInt32 inputAvailable = 0; | |||||
| UInt32 size = sizeof(inputAvailable); | |||||
| // we do not want to allow recording if input is not available | |||||
| err = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable); | |||||
| if (err != noErr) { | |||||
| fprintf(stderr, "kAudioSessionProperty_AudioInputAvailable error %d\n", err); | |||||
| } | |||||
| // we also need to listen to see if input availability changes | |||||
| err = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, PropListener, this); | |||||
| if (err != noErr) { | |||||
| fprintf(stderr, "kAudioSessionProperty_AudioInputAvailable error %d\n", err); | |||||
| } | |||||
| err = AudioSessionSetActive(true); | |||||
| if (err != noErr) { | |||||
| fprintf(stderr, "AudioSessionSetActive (true) failed %d", err); | |||||
| return -1; | |||||
| } | |||||
| */ | |||||
| AudioStreamBasicDescription captureDataFormat; | |||||
| /* | |||||
| captureDataFormat.mSampleRate = fSampleRate; | |||||
| captureDataFormat.mFormatID = kAudioFormatLinearPCM; | |||||
| //captureDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | |||||
| captureDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; | |||||
| captureDataFormat.mBytesPerPacket = sizeof(float); | |||||
| captureDataFormat.mFramesPerPacket = 1; | |||||
| captureDataFormat.mBytesPerFrame = sizeof(float); | |||||
| captureDataFormat.mChannelsPerFrame = fCaptureChannels; | |||||
| captureDataFormat.mBitsPerChannel = 32; | |||||
| */ | |||||
| captureDataFormat.mSampleRate = fSampleRate; | |||||
| captureDataFormat.mFormatID = kAudioFormatLinearPCM; | |||||
| captureDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; | |||||
| captureDataFormat.mBytesPerPacket = 4; | |||||
| captureDataFormat.mFramesPerPacket = 1; // this means each packet in the AQ has two samples, one for each channel -> 4 bytes/frame/packet | |||||
| captureDataFormat.mBytesPerFrame = 4; | |||||
| captureDataFormat.mChannelsPerFrame = 2; | |||||
| captureDataFormat.mBitsPerChannel = 16; | |||||
| if ((err = AudioQueueNewInput(&captureDataFormat, CaptureCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &fCaptureQueue)) != noErr) { | |||||
| Print4CharCode("error code : unknown", err); | |||||
| return -1; | |||||
| } | |||||
| size = sizeof(captureDataFormat.mSampleRate); | |||||
| if ((err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &size, &captureDataFormat.mSampleRate)) != noErr) { | |||||
| printf("couldn't get hardware sample rate\n"); | |||||
| } | |||||
| size = sizeof(captureDataFormat.mChannelsPerFrame); | |||||
| if ((err = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &size, &captureDataFormat.mChannelsPerFrame)) != noErr) { | |||||
| printf("couldn't get input channel count\n"); | |||||
| } | |||||
| size = sizeof(captureDataFormat); | |||||
| if ((err = AudioQueueGetProperty(fCaptureQueue, kAudioQueueProperty_StreamDescription, &captureDataFormat, &size)) != noErr) { | |||||
| printf("couldn't get queue's format\n"); | |||||
| } | |||||
| bufferByteSize = ComputeRecordBufferSize(fCaptureQueue, &captureDataFormat, kBufferDurationSeconds); // enough bytes for half a second | |||||
| for (int i = 0; i < kNumberBuffers; ++i) { | |||||
| if ((err = AudioQueueAllocateBuffer(fCaptureQueue, bufferByteSize, &fCaptureQueueBuffers[i])) != noErr) { | |||||
| printf("Capture AudioQueueAllocateBuffer failed\n"); | |||||
| } | |||||
| if ((err = AudioQueueEnqueueBuffer(fCaptureQueue, fCaptureQueueBuffers[i], 0, NULL)) != noErr) { | |||||
| printf("Capture AudioQueueEnqueueBuffer failed\n"); | |||||
| } | |||||
| } | |||||
| //AudioQueueSetProperty(fCaptureQueue, kAudioQueueProperty_MagicCookie, cookie, size) | |||||
| //AudioQueueSetProperty(fCaptureQueue, kAudioQueueProperty_ChannelLayout, acl, size | |||||
| AudioStreamBasicDescription playbackDataFormat; | |||||
| /* | |||||
| playbackDataFormat.mSampleRate = fSampleRate; | |||||
| playbackDataFormat.mFormatID = kAudioFormatLinearPCM; | |||||
| playbackDataFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | |||||
| playbackDataFormat.mBytesPerPacket = sizeof(float); | |||||
| playbackDataFormat.mFramesPerPacket = 1; | |||||
| playbackDataFormat.mBytesPerFrame = sizeof(float); | |||||
| playbackDataFormat.mChannelsPerFrame = fPlaybackChannels; | |||||
| playbackDataFormat.mBitsPerChannel = 32; | |||||
| */ | |||||
| playbackDataFormat.mSampleRate = fSampleRate; | |||||
| playbackDataFormat.mFormatID = kAudioFormatLinearPCM; | |||||
| playbackDataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; | |||||
| playbackDataFormat.mBytesPerPacket = 4; | |||||
| playbackDataFormat.mFramesPerPacket = 1; | |||||
| playbackDataFormat.mBytesPerFrame = 4; | |||||
| playbackDataFormat.mChannelsPerFrame = fPlaybackChannels; | |||||
| playbackDataFormat.mBitsPerChannel = 16; | |||||
| if ((err = AudioQueueNewOutput(&playbackDataFormat, PlaybackCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &fPlaybackQueue)) != noErr) { | |||||
| Print4CharCode("error code : unknown", err); | |||||
| return -1; | |||||
| } | |||||
| for (int i = 0; i < kNumberBuffers; ++i) { | |||||
| if ((err = AudioQueueAllocateBuffer(fPlaybackQueue, bufferByteSize, &fPlaybackQueueBuffers[i])) != noErr) { | |||||
| printf("Playback AudioQueueAllocateBuffer failed %d\n", err); | |||||
| } | |||||
| //if ((err = AudioQueueEnqueueBuffer(fPlaybackQueue, fPlaybackQueueBuffers[i], 0, NULL)) != noErr) { | |||||
| // printf("Playback AudioQueueEnqueueBuffer failed %d\n", err); | |||||
| //} | |||||
| } | |||||
| AudioQueueSetParameter(fPlaybackQueue, kAudioQueueParam_Volume, 1.0); | |||||
| //AudioQueueSetProperty(fPlaybackQueue, kAudioQueueProperty_MagicCookie, cookie, size); | |||||
| //AudioQueueSetProperty(fPlaybackQueue, kAudioQueueProperty_ChannelLayout, acl, size); | |||||
| //AudioQueueSetParameter(fPlaybackQueue, kAudioQueueParam_Volume, volume | |||||
| return 0; | |||||
| } | |||||
| int JackAudioQueueAdapter::Close() | |||||
| { | |||||
| //AudioSessionSetActive(false); | |||||
| AudioQueueDispose(fCaptureQueue, true); | |||||
| AudioQueueDispose(fPlaybackQueue, true); | |||||
| return 0; | |||||
| } | |||||
| int JackAudioQueueAdapter::Start() | |||||
| { | |||||
| for (int i = 0; i < kNumberBuffers; ++i) { | |||||
| PlaybackCallback(this, fPlaybackQueue, fPlaybackQueueBuffers[i]); | |||||
| } | |||||
| AudioQueueStart(fCaptureQueue, NULL); | |||||
| AudioQueueStart(fPlaybackQueue, NULL); | |||||
| return 0; | |||||
| } | |||||
| int JackAudioQueueAdapter::Stop() | |||||
| { | |||||
| AudioQueueStop(fCaptureQueue, NULL); | |||||
| AudioQueueStop(fPlaybackQueue, NULL); | |||||
| return 0; | |||||
| } | |||||
| int JackAudioQueueAdapter::SetSampleRate(jack_nframes_t sample_rate) | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| int JackAudioQueueAdapter::SetBufferSize(jack_nframes_t buffer_size) | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| }; | |||||
| @@ -1,99 +0,0 @@ | |||||
| /* | |||||
| Copyright (C) 2009 Grame | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| */ | |||||
| #ifndef __JackAudioQueueAdapter__ | |||||
| #define __JackAudioQueueAdapter__ | |||||
| //#include <AudioToolbox/AudioConverter.h> | |||||
| //#include <AudioToolbox/AudioQueue.h> | |||||
| #include <AudioToolbox/AudioToolbox.h> | |||||
| #include <jack/net.h> | |||||
| namespace Jack | |||||
| { | |||||
| /*! | |||||
| \brief Audio adapter using AudioQueue API. | |||||
| */ | |||||
| #define kNumberBuffers 3 | |||||
| #define kBufferDurationSeconds .5 | |||||
| class JackAudioQueueAdapter | |||||
| { | |||||
| private: | |||||
| AudioQueueRef fCaptureQueue; | |||||
| AudioQueueBufferRef fCaptureQueueBuffers[kNumberBuffers]; | |||||
| AudioQueueRef fPlaybackQueue; | |||||
| AudioQueueBufferRef fPlaybackQueueBuffers[kNumberBuffers]; | |||||
| //AudioStreamPacketDescription fPlaybackPacketDescs; | |||||
| jack_nframes_t fBufferSize; | |||||
| jack_nframes_t fSampleRate; | |||||
| int fCaptureChannels; | |||||
| int fPlaybackChannels; | |||||
| jack_adapter_t* fAdapter; | |||||
| static void CaptureCallback(void* inUserData, | |||||
| AudioQueueRef inAQ, | |||||
| AudioQueueBufferRef inBuffer, | |||||
| const AudioTimeStamp* inStartTime, | |||||
| UInt32 inNumPackets, | |||||
| const AudioStreamPacketDescription* inPacketDesc); | |||||
| static void PlaybackCallback(void* inUserData, | |||||
| AudioQueueRef inAQ, | |||||
| AudioQueueBufferRef inCompleteAQBuffer); | |||||
| static void InterruptionListener(void* inClientData, UInt32 inInterruptionState); | |||||
| static void PropListener(void* inClientData, | |||||
| AudioSessionPropertyID inID, | |||||
| UInt32 inDataSize, | |||||
| const void* inData); | |||||
| public: | |||||
| JackAudioQueueAdapter(int inchan, int outchan, jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_adapter_t* adapter); | |||||
| ~JackAudioQueueAdapter(); | |||||
| virtual int Open(); | |||||
| virtual int Close(); | |||||
| virtual int Start(); | |||||
| virtual int Stop(); | |||||
| virtual int SetSampleRate(jack_nframes_t sample_rate); | |||||
| virtual int SetBufferSize(jack_nframes_t buffer_size); | |||||
| }; | |||||
| } | |||||
| #endif | |||||
| @@ -0,0 +1,390 @@ | |||||
| /* | |||||
| Copyright (C) 2010 Grame | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| */ | |||||
| #include "TiPhoneCoreAudioRenderer.h" | |||||
| static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) | |||||
| { | |||||
| printf("- - - - - - - - - - - - - - - - - - - -\n"); | |||||
| printf(" Sample Rate:%f\n", inDesc->mSampleRate); | |||||
| printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID); | |||||
| printf(" Format Flags:%lX\n", inDesc->mFormatFlags); | |||||
| printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); | |||||
| printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); | |||||
| printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); | |||||
| printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); | |||||
| printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); | |||||
| printf("- - - - - - - - - - - - - - - - - - - -\n"); | |||||
| } | |||||
| static void printError(OSStatus err) | |||||
| { | |||||
| switch (err) { | |||||
| case kAudioConverterErr_FormatNotSupported: | |||||
| printf("error code : kAudioConverterErr_FormatNotSupported\n"); | |||||
| break; | |||||
| case kAudioConverterErr_OperationNotSupported: | |||||
| printf("error code : kAudioConverterErr_OperationNotSupported\n"); | |||||
| break; | |||||
| case kAudioConverterErr_PropertyNotSupported: | |||||
| printf("error code : kAudioConverterErr_PropertyNotSupported\n"); | |||||
| break; | |||||
| case kAudioConverterErr_InvalidInputSize: | |||||
| printf("error code : kAudioConverterErr_InvalidInputSize\n"); | |||||
| break; | |||||
| case kAudioConverterErr_InvalidOutputSize: | |||||
| printf("error code : kAudioConverterErr_InvalidOutputSize\n"); | |||||
| break; | |||||
| case kAudioConverterErr_UnspecifiedError: | |||||
| printf("error code : kAudioConverterErr_UnspecifiedError\n"); | |||||
| break; | |||||
| case kAudioConverterErr_BadPropertySizeError: | |||||
| printf("error code : kAudioConverterErr_BadPropertySizeError\n"); | |||||
| break; | |||||
| case kAudioConverterErr_RequiresPacketDescriptionsError: | |||||
| printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n"); | |||||
| break; | |||||
| case kAudioConverterErr_InputSampleRateOutOfRange: | |||||
| printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n"); | |||||
| break; | |||||
| case kAudioConverterErr_OutputSampleRateOutOfRange: | |||||
| printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n"); | |||||
| break; | |||||
| default: | |||||
| printf("error code : unknown\n"); | |||||
| break; | |||||
| } | |||||
| } | |||||
| OSStatus TiPhoneCoreAudioRenderer::Render(void *inRefCon, | |||||
| AudioUnitRenderActionFlags *ioActionFlags, | |||||
| const AudioTimeStamp *inTimeStamp, | |||||
| UInt32, | |||||
| UInt32 inNumberFrames, | |||||
| AudioBufferList *ioData) | |||||
| { | |||||
| TiPhoneCoreAudioRendererPtr renderer = (TiPhoneCoreAudioRendererPtr)inRefCon; | |||||
| AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData); | |||||
| float coef = float(LONG_MAX); | |||||
| float inv_coef = 1.f/float(LONG_MAX); | |||||
| for (int chan = 0; chan < renderer->fDevNumInChans; chan++) { | |||||
| for (int frame = 0; frame < inNumberFrames; frame++) { | |||||
| renderer->fInChannel[chan][frame] = float(((long*)ioData->mBuffers[chan].mData)[frame]) * inv_coef; | |||||
| } | |||||
| } | |||||
| renderer->PerformAudioCallback((int)inNumberFrames); | |||||
| for (int chan = 0; chan < renderer->fDevNumOutChans; chan++) { | |||||
| for (int frame = 0; frame < inNumberFrames; frame++) { | |||||
| ((long*)ioData->mBuffers[chan].mData)[frame] = long(renderer->fOutChannel[chan][frame] * coef); | |||||
| } | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 inInterruption) | |||||
| { | |||||
| TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData; | |||||
| printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption"); | |||||
| if (inInterruption == kAudioSessionEndInterruption) { | |||||
| // make sure we are again the active session | |||||
| AudioSessionSetActive(true); | |||||
| AudioOutputUnitStart(obj->fAUHAL); | |||||
| } | |||||
| if (inInterruption == kAudioSessionBeginInterruption) { | |||||
| AudioOutputUnitStop(obj->fAUHAL); | |||||
| } | |||||
| } | |||||
| int TiPhoneCoreAudioRenderer::OpenDefault(int bufferSize, int samplerate) | |||||
| { | |||||
| OSStatus err1; | |||||
| UInt32 outSize; | |||||
| UInt32 enableIO; | |||||
| AudioStreamBasicDescription srcFormat, dstFormat; | |||||
| printf("OpenDefault fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate); | |||||
| // Initialize and configure the audio session | |||||
| err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't initialize audio session\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } | |||||
| err1 = AudioSessionSetActive(true); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't set audio session active\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } | |||||
| UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; | |||||
| err1 = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't set audio category\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } | |||||
| //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener"); | |||||
| Float64 hwSampleRate; | |||||
| outSize = sizeof(hwSampleRate); | |||||
| err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't get hw sample rate\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } else { | |||||
| printf("Get hw sample rate %f\n", hwSampleRate); | |||||
| } | |||||
| Float32 hwBufferSize; | |||||
| outSize = sizeof(hwBufferSize); | |||||
| err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't get hw buffer duration\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } else { | |||||
| printf("Get hw buffer duration %f\n", hwBufferSize); | |||||
| } | |||||
| UInt32 hwInput; | |||||
| outSize = sizeof(hwInput); | |||||
| err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &hwInput); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't get hw input channels\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } else { | |||||
| printf("Get hw input channels %d\n", hwInput); | |||||
| } | |||||
| UInt32 hwOutput; | |||||
| outSize = sizeof(hwOutput); | |||||
| err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &hwOutput); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't get hw output channels\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } else { | |||||
| printf("Get hw output channels %d\n", hwOutput); | |||||
| } | |||||
| Float32 preferredBufferSize = float(bufferSize) / float(samplerate); | |||||
| printf("preferredBufferSize %f \n", preferredBufferSize); | |||||
| err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't set i/o buffer duration\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } | |||||
| Float64 preferredSamplerate = float(samplerate); | |||||
| err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't set i/o sample rate\n"); | |||||
| printError(err1); | |||||
| return OPEN_ERR; | |||||
| } | |||||
| // AUHAL | |||||
| AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0}; | |||||
| AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd); | |||||
| err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling OpenAComponent\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| enableIO = 1; | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| enableIO = 1; | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| UInt32 maxFPS; | |||||
| outSize = sizeof(maxFPS); | |||||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize); | |||||
| if (err1 != noErr) { | |||||
| printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } else { | |||||
| printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS); | |||||
| } | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| err1 = AudioUnitInitialize(fAUHAL); | |||||
| if (err1 != noErr) { | |||||
| printf("Cannot initialize AUHAL unit\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| // Setting format | |||||
| if (fDevNumInChans > 0) { | |||||
| outSize = sizeof(AudioStreamBasicDescription); | |||||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); | |||||
| printError(err1); | |||||
| } | |||||
| PrintStreamDesc(&srcFormat); | |||||
| srcFormat.mFormatID = kAudioFormatLinearPCM; | |||||
| srcFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; | |||||
| srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); | |||||
| srcFormat.mFramesPerPacket = 1; | |||||
| srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); | |||||
| srcFormat.mChannelsPerFrame = fDevNumInChans; | |||||
| srcFormat.mBitsPerChannel = 32; | |||||
| PrintStreamDesc(&srcFormat); | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n"); | |||||
| printError(err1); | |||||
| } | |||||
| } | |||||
| if (fDevNumOutChans > 0) { | |||||
| outSize = sizeof(AudioStreamBasicDescription); | |||||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); | |||||
| printError(err1); | |||||
| } | |||||
| PrintStreamDesc(&dstFormat); | |||||
| dstFormat.mFormatID = kAudioFormatLinearPCM; | |||||
| dstFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved; | |||||
| dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType); | |||||
| dstFormat.mFramesPerPacket = 1; | |||||
| dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType); | |||||
| dstFormat.mChannelsPerFrame = fDevNumOutChans; | |||||
| dstFormat.mBitsPerChannel = 32; | |||||
| PrintStreamDesc(&dstFormat); | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n"); | |||||
| printError(err1); | |||||
| } | |||||
| } | |||||
| if (fDevNumInChans > 0 && fDevNumOutChans == 0) { | |||||
| AURenderCallbackStruct output; | |||||
| output.inputProc = Render; | |||||
| output.inputProcRefCon = this; | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| } else { | |||||
| AURenderCallbackStruct output; | |||||
| output.inputProc = Render; | |||||
| output.inputProcRefCon = this; | |||||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output)); | |||||
| if (err1 != noErr) { | |||||
| printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n"); | |||||
| printError(err1); | |||||
| goto error; | |||||
| } | |||||
| } | |||||
| return NO_ERR; | |||||
| error: | |||||
| AudioUnitUninitialize(fAUHAL); | |||||
| AudioComponentInstanceDispose(fAUHAL); | |||||
| return OPEN_ERR; | |||||
| } | |||||
| int TiPhoneCoreAudioRenderer::Close() | |||||
| { | |||||
| AudioUnitUninitialize(fAUHAL); | |||||
| AudioComponentInstanceDispose(fAUHAL); | |||||
| return NO_ERR; | |||||
| } | |||||
| int TiPhoneCoreAudioRenderer::Start() | |||||
| { | |||||
| AudioSessionSetActive(true); | |||||
| OSStatus err = AudioOutputUnitStart(fAUHAL); | |||||
| if (err != noErr) { | |||||
| printf("Error while opening device : device open error \n"); | |||||
| return OPEN_ERR; | |||||
| } else { | |||||
| return NO_ERR; | |||||
| } | |||||
| } | |||||
| int TiPhoneCoreAudioRenderer::Stop() | |||||
| { | |||||
| OSStatus err = AudioOutputUnitStop(fAUHAL); | |||||
| if (err != noErr) { | |||||
| printf("Error while closing device : device close error \n"); | |||||
| return OPEN_ERR; | |||||
| } else { | |||||
| return NO_ERR; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,103 @@ | |||||
| /* | |||||
| Copyright (C) 2010 Grame | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| */ | |||||
| #ifndef __TiPhoneCoreAudioRenderer__ | |||||
| #define __TiPhoneCoreAudioRenderer__ | |||||
| #include <AudioToolbox/AudioConverter.h> | |||||
| #include <AudioToolbox/AudioServices.h> | |||||
| #include <AudioUnit/AudioUnit.h> | |||||
| #define MAX_CHANNELS 256 | |||||
| #define OPEN_ERR -1 | |||||
| #define NO_ERR 0 | |||||
| typedef void (*AudioCallback) (int frames, float** inputs, float** outputs, void* arg); | |||||
| class TiPhoneCoreAudioRenderer | |||||
| { | |||||
| private: | |||||
| AudioUnit fAUHAL; | |||||
| AudioCallback fAudioCallback; | |||||
| void* fCallbackArg; | |||||
| int fDevNumInChans; | |||||
| int fDevNumOutChans; | |||||
| float* fInChannel[MAX_CHANNELS]; | |||||
| float* fOutChannel[MAX_CHANNELS]; | |||||
| static OSStatus Render(void *inRefCon, | |||||
| AudioUnitRenderActionFlags *ioActionFlags, | |||||
| const AudioTimeStamp *inTimeStamp, | |||||
| UInt32 inBusNumber, | |||||
| UInt32 inNumberFrames, | |||||
| AudioBufferList *ioData); | |||||
| static void InterruptionListener(void *inClientData, UInt32 inInterruption); | |||||
| public: | |||||
| TiPhoneCoreAudioRenderer(int input, int output) | |||||
| :fDevNumInChans(input), fDevNumOutChans(output), fAudioCallback(NULL), fCallbackArg(NULL) | |||||
| { | |||||
| for (int i = 0; i < fDevNumInChans; i++) { | |||||
| fInChannel[i] = new float[8192]; | |||||
| } | |||||
| for (int i = 0; i < fDevNumOutChans; i++) { | |||||
| fOutChannel[i] = new float[8192]; | |||||
| } | |||||
| } | |||||
| virtual ~TiPhoneCoreAudioRenderer() | |||||
| { | |||||
| for (int i = 0; i < fDevNumInChans; i++) { | |||||
| delete[] fInChannel[i]; | |||||
| } | |||||
| for (int i = 0; i < fDevNumOutChans; i++) { | |||||
| delete[] fOutChannel[i]; | |||||
| } | |||||
| } | |||||
| int OpenDefault(int bufferSize, int sampleRate); | |||||
| int Close(); | |||||
| int Start(); | |||||
| int Stop(); | |||||
| void SetAudioCallback(AudioCallback callback, void* arg) | |||||
| { | |||||
| fAudioCallback = callback; | |||||
| fCallbackArg = arg; | |||||
| } | |||||
| void PerformAudioCallback(int frames) | |||||
| { | |||||
| if (fAudioCallback) | |||||
| fAudioCallback(frames, fInChannel, fOutChannel, fCallbackArg); | |||||
| } | |||||
| }; | |||||
| typedef TiPhoneCoreAudioRenderer * TiPhoneCoreAudioRendererPtr; | |||||
| #endif | |||||
| @@ -19,7 +19,6 @@ | |||||
| 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; | 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; }; | ||||
| 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; | 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; }; | ||||
| 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; | 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; }; | ||||
| 4B07722B0F54018C000DC657 /* JackAudioQueueAdapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A947D0F49C42300D3626B /* JackAudioQueueAdapter.cpp */; }; | |||||
| 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; | 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; }; | ||||
| 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; | 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; }; | ||||
| 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; | 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; }; | ||||
| @@ -116,6 +115,12 @@ | |||||
| 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; | 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; | ||||
| 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; | 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; | ||||
| 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; | 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; }; | ||||
| 4BF15F7811357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; | |||||
| 4BF15F7911357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; | |||||
| 4BF15F7A11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; | |||||
| 4BF15F7B11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; | |||||
| 4BF15F7C11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; | |||||
| 4BF15F7D11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; }; | |||||
| 4BFF45600F4D5D9700106083 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; | 4BFF45600F4D5D9700106083 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; | ||||
| 4BFF45630F4D5D9700106083 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; | 4BFF45630F4D5D9700106083 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; }; | ||||
| 4BFF45640F4D5D9700106083 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; | 4BFF45640F4D5D9700106083 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; }; | ||||
| @@ -173,6 +178,7 @@ | |||||
| 4BF1364C0F4B0F7700218A3F /* JackResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackResampler.h; path = ../../common/JackResampler.h; sourceTree = SOURCE_ROOT; }; | 4BF1364C0F4B0F7700218A3F /* JackResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackResampler.h; path = ../../common/JackResampler.h; sourceTree = SOURCE_ROOT; }; | ||||
| 4BF136540F4B0F9F00218A3F /* ringbuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ringbuffer.c; path = ../../common/ringbuffer.c; sourceTree = SOURCE_ROOT; }; | 4BF136540F4B0F9F00218A3F /* ringbuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ringbuffer.c; path = ../../common/ringbuffer.c; sourceTree = SOURCE_ROOT; }; | ||||
| 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CAHostTimeBase.cpp; path = /Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.cpp; sourceTree = "<absolute>"; }; | 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CAHostTimeBase.cpp; path = /Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.cpp; sourceTree = "<absolute>"; }; | ||||
| 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TiPhoneCoreAudioRenderer.cpp; path = ../coreaudio/TiPhoneCoreAudioRenderer.cpp; sourceTree = SOURCE_ROOT; }; | |||||
| 4BFF45120F4D59DB00106083 /* libjacknet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjacknet.a; sourceTree = BUILT_PRODUCTS_DIR; }; | 4BFF45120F4D59DB00106083 /* libjacknet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjacknet.a; sourceTree = BUILT_PRODUCTS_DIR; }; | ||||
| 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; | 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; | ||||
| 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | ||||
| @@ -275,6 +281,7 @@ | |||||
| 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */, | 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */, | ||||
| 4BCB37D5112D64B4008C7BC1 /* HardwareClock.cpp */, | 4BCB37D5112D64B4008C7BC1 /* HardwareClock.cpp */, | ||||
| 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */, | 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */, | ||||
| 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */, | |||||
| 29B97315FDCFA39411CA2CEA /* Other Sources */, | 29B97315FDCFA39411CA2CEA /* Other Sources */, | ||||
| 29B97317FDCFA39411CA2CEA /* Resources */, | 29B97317FDCFA39411CA2CEA /* Resources */, | ||||
| 29B97323FDCFA39411CA2CEA /* Frameworks */, | 29B97323FDCFA39411CA2CEA /* Frameworks */, | ||||
| @@ -567,6 +574,7 @@ | |||||
| 4B0773870F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, | 4B0773870F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, | ||||
| 4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */, | 4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */, | ||||
| 4BF15E2611356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | 4BF15E2611356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | ||||
| 4BF15F7911357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, | |||||
| ); | ); | ||||
| runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
| }; | }; | ||||
| @@ -581,7 +589,6 @@ | |||||
| 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */, | 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */, | ||||
| 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */, | 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */, | ||||
| 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */, | 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */, | ||||
| 4B07722B0F54018C000DC657 /* JackAudioQueueAdapter.cpp in Sources */, | |||||
| 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */, | 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */, | ||||
| 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */, | 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */, | ||||
| 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */, | 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */, | ||||
| @@ -589,6 +596,7 @@ | |||||
| 4B0773860F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, | 4B0773860F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */, | ||||
| 4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */, | 4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */, | ||||
| 4BF15E2511356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | 4BF15E2511356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | ||||
| 4BF15F7811357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, | |||||
| ); | ); | ||||
| runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
| }; | }; | ||||
| @@ -629,6 +637,7 @@ | |||||
| 4B4146A610BD3C4300C12F0C /* freeverb.mm in Sources */, | 4B4146A610BD3C4300C12F0C /* freeverb.mm in Sources */, | ||||
| 4B4146A710BD3C4300C12F0C /* JackGlobals.cpp in Sources */, | 4B4146A710BD3C4300C12F0C /* JackGlobals.cpp in Sources */, | ||||
| 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | ||||
| 4BF15F7C11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, | |||||
| ); | ); | ||||
| runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
| }; | }; | ||||
| @@ -639,6 +648,7 @@ | |||||
| 4BCB37D6112D64B4008C7BC1 /* HardwareClock.cpp in Sources */, | 4BCB37D6112D64B4008C7BC1 /* HardwareClock.cpp in Sources */, | ||||
| 4BCB37D9112D64D8008C7BC1 /* iphone-faust.mm in Sources */, | 4BCB37D9112D64D8008C7BC1 /* iphone-faust.mm in Sources */, | ||||
| 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | ||||
| 4BF15F7D11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, | |||||
| ); | ); | ||||
| runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
| }; | }; | ||||
| @@ -661,6 +671,7 @@ | |||||
| 4BCF75E910BC2FD90082C526 /* JackGlobals.cpp in Sources */, | 4BCF75E910BC2FD90082C526 /* JackGlobals.cpp in Sources */, | ||||
| 4BCF75F710BC30140082C526 /* audio_thru.mm in Sources */, | 4BCF75F710BC30140082C526 /* audio_thru.mm in Sources */, | ||||
| 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | ||||
| 4BF15F7B11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, | |||||
| ); | ); | ||||
| runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
| }; | }; | ||||
| @@ -683,6 +694,7 @@ | |||||
| 4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */, | 4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */, | ||||
| 4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */, | 4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */, | ||||
| 4BF15E2711356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | 4BF15E2711356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */, | ||||
| 4BF15F7A11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */, | |||||
| ); | ); | ||||
| runOnlyForDeploymentPostprocessing = 0; | runOnlyForDeploymentPostprocessing = 0; | ||||
| }; | }; | ||||
| @@ -747,6 +759,7 @@ | |||||
| GCC_PRECOMPILE_PREFIX_HEADER = YES; | GCC_PRECOMPILE_PREFIX_HEADER = YES; | ||||
| GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; | GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; | ||||
| HEADER_SEARCH_PATHS = ( | HEADER_SEARCH_PATHS = ( | ||||
| ../../macosx/coreaudio, | |||||
| ../../macosx, | ../../macosx, | ||||
| ../../posix, | ../../posix, | ||||
| ../../common/jack, | ../../common/jack, | ||||
| @@ -771,6 +784,7 @@ | |||||
| GCC_PRECOMPILE_PREFIX_HEADER = YES; | GCC_PRECOMPILE_PREFIX_HEADER = YES; | ||||
| GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; | GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch; | ||||
| HEADER_SEARCH_PATHS = ( | HEADER_SEARCH_PATHS = ( | ||||
| ../../macosx/coreaudio, | |||||
| ../../common/jack, | ../../common/jack, | ||||
| ../../common, | ../../common, | ||||
| ../../posix, | ../../posix, | ||||
| @@ -9,7 +9,7 @@ | |||||
| #import <UIKit/UIKit.h> | #import <UIKit/UIKit.h> | ||||
| #include <jack/net.h> | #include <jack/net.h> | ||||
| #include "JackAudioQueueAdapter.h" | |||||
| #include "TiPhoneCoreAudioRenderer.h" | |||||
| #define NUM_INPUT 2 | #define NUM_INPUT 2 | ||||
| #define NUM_OUTPUT 2 | #define NUM_OUTPUT 2 | ||||
| @@ -17,27 +17,34 @@ | |||||
| jack_net_master_t* net; | jack_net_master_t* net; | ||||
| jack_adapter_t* adapter; | jack_adapter_t* adapter; | ||||
| Jack::JackAudioQueueAdapter* audio; | |||||
| float** audio_input_buffer; | |||||
| float** audio_output_buffer; | |||||
| static int net_process(jack_nframes_t buffer_size, | |||||
| int audio_input, | |||||
| float** audio_input_buffer, | |||||
| int midi_input, | |||||
| void** midi_input_buffer, | |||||
| int audio_output, | |||||
| float** audio_output_buffer, | |||||
| int midi_output, | |||||
| void** midi_output_buffer, | |||||
| void* data) | |||||
| int buffer_size = 2048; | |||||
| int sample_rate = 44100; | |||||
| jack_master_t request = { buffer_size, sample_rate, "master" }; | |||||
| jack_slave_t result; | |||||
| void MasterAudioCallback(int frames, float** inputs, float** outputs, void* arg) | |||||
| { | { | ||||
| // Process input, produce output | |||||
| if (audio_input == audio_output) { | |||||
| // Copy input to output | |||||
| for (int i = 0; i < audio_input; i++) { | |||||
| memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float)); | |||||
| } | |||||
| int i; | |||||
| for (i = 0; i < result.audio_input; i++) { | |||||
| memcpy(audio_output_buffer[i], inputs[i], buffer_size * sizeof(float)); | |||||
| } | |||||
| if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) { | |||||
| printf("jack_net_master_send error..\n"); | |||||
| } | |||||
| if (jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) { | |||||
| printf("jack_net_master_recv error..\n"); | |||||
| } | |||||
| for (i = 0; i < result.audio_output; i++) { | |||||
| memcpy(outputs[i], audio_input_buffer[i], buffer_size * sizeof(float)); | |||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||
| @@ -45,14 +52,9 @@ int main(int argc, char *argv[]) { | |||||
| NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; | ||||
| int i; | int i; | ||||
| int buffer_size = 2048; | |||||
| int sample_rate = 44100; | |||||
| jack_master_t request = { buffer_size, sample_rate, "master" }; | |||||
| jack_slave_t result; | |||||
| float** audio_input_buffer; | |||||
| float** audio_output_buffer; | |||||
| int wait_usec = (int) ((((float)buffer_size) * 1000000) / ((float)sample_rate)); | |||||
| TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT); | |||||
| if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { | if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| @@ -68,8 +70,24 @@ int main(int argc, char *argv[]) { | |||||
| audio_output_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); | audio_output_buffer[i] = (float*)(calloc(buffer_size, sizeof(float))); | ||||
| } | } | ||||
| // Quite brutal way, the application actually does not start completely, the netjack audio processing loop is used instead... | |||||
| if (audio_device.OpenDefault(buffer_size, sample_rate) < 0) { | |||||
| return -1; | |||||
| } | |||||
| audio_device.SetAudioCallback(MasterAudioCallback, NULL); | |||||
| if (audio_device.Start() < 0) { | |||||
| return -1; | |||||
| } | |||||
| // Run until interrupted | |||||
| while (1) {} | |||||
| audio_device.Stop(); | |||||
| audio_device.Close(); | |||||
| /* | |||||
| // Quite brutal way, the application actually does not start completely, the netjack audio processing loop is used instead... | |||||
| // Run until interrupted | // Run until interrupted | ||||
| while (1) { | while (1) { | ||||
| @@ -89,6 +107,7 @@ int main(int argc, char *argv[]) { | |||||
| } | } | ||||
| usleep(wait_usec); | usleep(wait_usec); | ||||
| }; | }; | ||||
| */ | |||||
| // Wait for application end | // Wait for application end | ||||
| jack_net_master_close(net); | jack_net_master_close(net); | ||||
| @@ -9,16 +9,12 @@ | |||||
| #import <UIKit/UIKit.h> | #import <UIKit/UIKit.h> | ||||
| #include <jack/net.h> | #include <jack/net.h> | ||||
| #include "JackAudioQueueAdapter.h" | |||||
| #define NUM_INPUT 2 | #define NUM_INPUT 2 | ||||
| #define NUM_OUTPUT 2 | #define NUM_OUTPUT 2 | ||||
| jack_net_slave_t* net; | jack_net_slave_t* net; | ||||
| jack_adapter_t* adapter; | jack_adapter_t* adapter; | ||||
| Jack::JackAudioQueueAdapter* audio; | |||||
| static int net_process(jack_nframes_t buffer_size, | static int net_process(jack_nframes_t buffer_size, | ||||
| int audio_input, | int audio_input, | ||||
| float** audio_input_buffer, | float** audio_input_buffer, | ||||