Browse Source

Correct sample_rate management in JackCoreAudioDriver::Open. Better handling in sample_rate change listener.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1723 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.69
sletz 18 years ago
parent
commit
0b499549e9
3 changed files with 131 additions and 55 deletions
  1. +4
    -0
      ChangeLog
  2. +114
    -52
      macosx/JackCoreAudioDriver.cpp
  3. +13
    -3
      macosx/JackCoreAudioDriver.h

+ 4
- 0
ChangeLog View File

@@ -15,6 +15,10 @@ Kjetil S.Matheussen
Jackdmp changes log
---------------------------

2007-12-05 Stephane Letz <letz@grame.fr>

* Correct sample_rate management in JackCoreAudioDriver::Open. Better handling in sample_rate change listener.

2007-12-04 Stephane Letz <letz@grame.fr>

* Add a sample_rate change listener in CoreAudio driver.


+ 114
- 52
macosx/JackCoreAudioDriver.cpp View File

@@ -193,7 +193,7 @@ OSStatus JackCoreAudioDriver::Render(void *inRefCon,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
driver->fLastWaitUst = GetMicroSeconds(); // Take callback date here
memcpy(&driver->fActionFags, ioActionFlags, sizeof(AudioUnitRenderActionFlags));
memcpy(&driver->fCurrentTime, inTimeStamp, sizeof(AudioTimeStamp));
@@ -243,6 +243,26 @@ OSStatus JackCoreAudioDriver::MeasureCallback(AudioDeviceID inDevice,
return noErr;
}

OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel,
Boolean isInput,
AudioDevicePropertyID inPropertyID,
void* inClientData)
{
JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
switch (inPropertyID) {

case kAudioDevicePropertyNominalSampleRate: {
JackLog("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate \n");
driver->fState = true;
break;
}
}
return noErr;
}

OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel,
Boolean isInput,
@@ -250,6 +270,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
void* inClientData)
{
JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
switch (inPropertyID) {
case kAudioDeviceProcessorOverload:
@@ -263,6 +284,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
case kAudioDevicePropertyNominalSampleRate: {
UInt32 outSize = sizeof(Float64);
Float64 sampleRate;
AudioStreamBasicDescription srcFormat, dstFormat;
OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
if (err != noErr) {
jack_error("Cannot get current sample rate");
@@ -270,9 +292,32 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
return kAudioHardwareUnsupportedOperationError;
}
JackLog("JackCoreAudioDriver::NotificationCallback kAudioDevicePropertyNominalSampleRate %ld\n", long(sampleRate));
if (jack_nframes_t(sampleRate) != driver->fEngineControl->fSampleRate) {
AudioUnitUninitialize(driver->fAUHAL);
jack_error("Critical error: new %ld sample rate, coreaudio driver is stopped", long(sampleRate));
outSize = sizeof(AudioStreamBasicDescription);
// Update SR for input
err = AudioUnitGetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, &outSize);
if (err != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
printError(err);
}
srcFormat.mSampleRate = sampleRate;
err = AudioUnitSetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, outSize);
if (err != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
printError(err);
}
// Update SR for output
err = AudioUnitGetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, &outSize);
if (err != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
printError(err);
}
dstFormat.mSampleRate = sampleRate;
err = AudioUnitSetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, outSize);
if (err != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
printError(err);
}
break;
}
@@ -400,7 +445,7 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, long* chann
}

JackCoreAudioDriver::JackCoreAudioDriver(const char* name, JackEngine* engine, JackSynchro** table)
: JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL)
: JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL), fState(false)
{
#ifdef DEBUG
//fLogFile = new CALatencyLog("jackmp_latency", ".txt");
@@ -437,8 +482,6 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
long out_nChannels = 0;
char capture_driver_name[256];
char playback_driver_name[256];
float iousage;

capture_driver_name[0] = 0;
playback_driver_name[0] = 0;

@@ -446,7 +489,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
nframes, inchannels, outchannels, capture_driver_uid, playback_driver_uid);

// Duplex
if (capture_driver_uid != NULL && playback_driver_uid != NULL) {
if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
JackLog("JackCoreAudioDriver::Open duplex \n");
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
if (GetDefaultDevice(&fDeviceID) != noErr) {
@@ -459,8 +502,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
return -1;
}

// Capture only
} else if (capture_driver_uid != NULL) {
// Capture only
} else if (strcmp(capture_driver_uid, "") != 0) {
JackLog("JackCoreAudioDriver::Open capture only \n");
if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
if (GetDefaultInputDevice(&fDeviceID) != noErr) {
@@ -473,8 +516,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
return -1;
}

// Playback only
} else if (playback_driver_uid != NULL) {
// Playback only
} else if (strcmp(playback_driver_uid, "") != 0) {
JackLog("JackCoreAudioDriver::Open playback only \n");
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
@@ -487,7 +530,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
return -1;
}

// Use default driver in duplex mode
// Use default driver in duplex mode
} else {
JackLog("JackCoreAudioDriver::Open default driver \n");
if (GetDefaultDevice(&fDeviceID) != noErr) {
@@ -552,7 +595,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
return -1;
}

// Set sample rate
// Get sample rate
outSize = sizeof(Float64);
err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
if (err != noErr) {
@@ -561,16 +604,35 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
return -1;
}

// If needed, set new sample rate
if (samplerate != (jack_nframes_t)sampleRate) {
sampleRate = (Float64)samplerate;
// To get SR change notification
err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
if (err != noErr) {
jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
printError(err);
return -1;
}
err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
if (err != noErr) {
jack_error("Cannot set sample rate = %ld", samplerate);
printError(err);
return -1;
}
// Waiting for SR change notification
int count = 0;
while (!fState && count++ < 100) {
usleep(100000);
JackLog("Wait count = %ld\n", count);
}
// Remove SR change notification
AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
}
// AUHAL
ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
Component HALOutput = FindNextComponent(NULL, &cd);
@@ -621,7 +683,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,

// Set buffer size
if (capturing && inchannels > 0) {
err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*) & nframes, sizeof(UInt32));
err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&nframes, sizeof(UInt32));
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
printError(err1);
@@ -630,7 +692,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
}

if (playing && outchannels > 0) {
err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*) & nframes, sizeof(UInt32));
err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&nframes, sizeof(UInt32));
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
printError(err1);
@@ -670,40 +732,40 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
}

// Setup stream converters
if (capturing && inchannels > 0) {
srcFormat.mSampleRate = samplerate;
srcFormat.mFormatID = kAudioFormatLinearPCM;
srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
srcFormat.mBytesPerPacket = sizeof(float);
srcFormat.mFramesPerPacket = 1;
srcFormat.mBytesPerFrame = sizeof(float);
srcFormat.mChannelsPerFrame = outchannels;
srcFormat.mBitsPerChannel = 32;

err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
printError(err1);
}
}

if (playing && outchannels > 0) {
dstFormat.mSampleRate = samplerate;
dstFormat.mFormatID = kAudioFormatLinearPCM;
dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
dstFormat.mBytesPerPacket = sizeof(float);
dstFormat.mFramesPerPacket = 1;
dstFormat.mBytesPerFrame = sizeof(float);
dstFormat.mChannelsPerFrame = inchannels;
dstFormat.mBitsPerChannel = 32;

err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
printError(err1);
}
}
JackLog("Setup AUHAL input stream converter SR = %ld\n", samplerate);
srcFormat.mSampleRate = samplerate;
srcFormat.mFormatID = kAudioFormatLinearPCM;
srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
srcFormat.mBytesPerPacket = sizeof(float);
srcFormat.mFramesPerPacket = 1;
srcFormat.mBytesPerFrame = sizeof(float);
srcFormat.mChannelsPerFrame = outchannels;
srcFormat.mBitsPerChannel = 32;
err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
printError(err1);
goto error;
}

JackLog("Setup AUHAL output stream converter SR = %ld\n", samplerate);
dstFormat.mSampleRate = samplerate;
dstFormat.mFormatID = kAudioFormatLinearPCM;
dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
dstFormat.mBytesPerPacket = sizeof(float);
dstFormat.mFramesPerPacket = 1;
dstFormat.mBytesPerFrame = sizeof(float);
dstFormat.mChannelsPerFrame = inchannels;
dstFormat.mBitsPerChannel = 32;

err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
if (err1 != noErr) {
jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
printError(err1);
goto error;
}
// Setup callbacks
if (inchannels > 0 && outchannels == 0) {
AURenderCallbackStruct output;
@@ -762,7 +824,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
printError(err1);
goto error;
}
fDriverOutputData = 0;

#if IO_CPU
@@ -778,7 +840,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes,
// Core driver may have changed the in/out values
fCaptureChannels = inchannels;
fPlaybackChannels = outchannels;
return 0;
return noErr;

error:
AudioUnitUninitialize(fAUHAL);


+ 13
- 3
macosx/JackCoreAudioDriver.h View File

@@ -53,9 +53,10 @@ class JackCoreAudioDriver : public JackAudioDriver
{

private:
#ifdef DEBUG
#ifdef DEBUG
//CALatencyLog* fLogFile;
#endif
#endif

AudioUnit fAUHAL;

@@ -66,6 +67,8 @@ class JackCoreAudioDriver : public JackAudioDriver

AudioUnitRenderActionFlags fActionFags;
AudioTimeStamp fCurrentTime;
bool fState;

static OSStatus Render(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
@@ -87,7 +90,14 @@ class JackCoreAudioDriver : public JackAudioDriver
Boolean isInput,
AudioDevicePropertyID inPropertyID,
void* inClientData);

static OSStatus SRNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel,
Boolean isInput,
AudioDevicePropertyID inPropertyID,
void* inClientData);
OSStatus GetDeviceIDFromUID(const char* UID, AudioDeviceID* id);
OSStatus GetDefaultDevice(AudioDeviceID* id);
OSStatus GetDefaultInputDevice(AudioDeviceID* id);


Loading…
Cancel
Save