Commit 993363a9 authored by Stephane Letz's avatar Stephane Letz
Browse files

New JackAC3Encoder class.

parent 2c6ba8dc
/*
Copyright (C) 2006 Jesse Chappell <jesse@essej.net> (AC3Jack)
Copyright (C) 2012 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 "JackAC3Encoder.h"
#include "JackError.h"
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#define max(x,y) (((x)>(y)) ? (x) : (y))
#define min(x,y) (((x)<(y)) ? (x) : (y))
namespace Jack
{
JackAC3Encoder::JackAC3Encoder(const JackAC3EncoderParams& params)
{
aften_set_defaults(&fAftenContext);
fAftenContext.channels = params.channels;
fAftenContext.samplerate = params.sample_rate;
fAftenContext.params.bitrate = params.bitrate;
int acmod = A52_ACMOD_MONO;
int lfe = params.lfe;
switch (params.channels) {
case 1: acmod = A52_ACMOD_MONO; break;
case 2: acmod = A52_ACMOD_STEREO; break;
case 3: acmod = A52_ACMOD_3_0; break;
case 4: acmod = A52_ACMOD_2_2; break;
case 5: acmod = A52_ACMOD_3_2; break;
break;
default:
break;
}
if (lfe) {
fAftenContext.channels += 1;
}
fAftenContext.acmod = acmod;
fAftenContext.lfe = lfe;
fAftenContext.sample_format = A52_SAMPLE_FMT_FLT;
fAftenContext.verbose = 1;
fAftenContext.system.n_threads = 1;
// create interleaved framebuffer for MAX_AC3_CHANNELS
fSampleBuffer = new float[MAX_AC3_CHANNELS * A52_SAMPLES_PER_FRAME];
// create AC3 buffer
fAC3Buffer = new unsigned char[A52_MAX_CODED_FRAME_SIZE];
memset(fAC3Buffer, 0, A52_MAX_CODED_FRAME_SIZE);
fZeroBuffer = new unsigned char[SPDIF_FRAME_SIZE];
memset(fZeroBuffer, 0, SPDIF_FRAME_SIZE);
fRingBuffer = jack_ringbuffer_create(32768);
fOutSizeByte = 0;
fFramePos = 0;
fSampleRate = 0;
fByteRate = 0;
}
bool JackAC3Encoder::Init(jack_nframes_t sample_rate)
{
fSampleRate = sample_rate;
fByteRate = fSampleRate * sizeof(short) * 2;
return (aften_encode_init(&fAftenContext) == 0);
}
JackAC3Encoder::~JackAC3Encoder()
{
aften_encode_close(&fAftenContext);
delete [] fSampleBuffer;
delete [] fAC3Buffer;
delete [] fZeroBuffer;
if (fRingBuffer) {
jack_ringbuffer_free(fRingBuffer);
}
}
void JackAC3Encoder::Process(float** inputs_buffer, float** outputs_buffer, int nframes)
{
// fill and process frame buffers as appropriate
jack_nframes_t frames_left = A52_SAMPLES_PER_FRAME - fFramePos;
jack_nframes_t offset = 0;
while (offset < nframes)
{
if ((nframes - offset) >= frames_left) {
// copy only frames_left more data
jack_nframes_t pos = fFramePos * fAftenContext.channels;
for (jack_nframes_t spos = offset; spos < offset + frames_left; ++spos) {
for (size_t i = 0; i < fAftenContext.channels; ++i) {
fSampleBuffer[pos + i] = inputs_buffer[i][spos];
}
pos += fAftenContext.channels;
}
// use interleaved version
int res = aften_encode_frame(&fAftenContext, fAC3Buffer + SPDIF_HEADER_SIZE, fSampleBuffer);
if (res < 0) {
jack_error("aften_encode_frame error !!");
return;
}
fOutSizeByte = res;
FillSpdifHeader(fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE);
// push AC3 output to SPDIF ring buffer
float calc_ac3byterate = (fOutSizeByte * fSampleRate / (float) A52_SAMPLES_PER_FRAME);
jack_nframes_t silencebytes = (jack_nframes_t) (fOutSizeByte * (fByteRate / calc_ac3byterate)) - fOutSizeByte - SPDIF_HEADER_SIZE;
jack_ringbuffer_write(fRingBuffer, (const char *)fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE);
// write the proper remainder of zero padding (inefficient, should be memsetting)
jack_ringbuffer_write(fRingBuffer, (const char *)fZeroBuffer, silencebytes);
offset += frames_left;
frames_left = A52_SAMPLES_PER_FRAME;
fFramePos = 0;
} else {
// copy incoming data into frame buffers without processing
jack_nframes_t pos = fFramePos * fAftenContext.channels;
for (jack_nframes_t spos = offset; spos < nframes; ++spos) {
for (size_t i = 0; i < fAftenContext.channels; ++i) {
fSampleBuffer[pos + i] = inputs_buffer[i][spos];
}
pos += fAftenContext.channels;
}
fFramePos += (nframes - offset);
offset += (nframes-offset);
}
}
Output2Driver(outputs_buffer, nframes);
}
void JackAC3Encoder::FillSpdifHeader(unsigned char* buf, int outsize)
{
// todo, use outsize and not assume the fixed frame size?
int ac3outsize = outsize - SPDIF_HEADER_SIZE;
buf[0] = 0x72; buf[1] = 0xf8; /* spdif syncword */
buf[2] = 0x1f; buf[3] = 0x4e; /* .............. */
buf[4] = 0x01; /* AC3 data */
buf[5] = buf[13] & 7; /* bsmod, stream = 0 */
buf[6] = (ac3outsize << 3) & 0xff;
buf[7] = (ac3outsize >> 5) & 0xff;
#if !IS_BIGENDIAN
swab(buf+SPDIF_HEADER_SIZE, buf + SPDIF_HEADER_SIZE, ac3outsize);
#endif
}
int JackAC3Encoder::Output2Driver(float** outputs, jack_nframes_t nframes)
{
int wrotebytes = 0;
jack_nframes_t nframes_left = nframes;
if (jack_ringbuffer_read_space(fRingBuffer) == 0) {
// just write silence
memset(outputs[0], 0, nframes * sizeof(jack_default_audio_sample_t));
memset(outputs[1], 0, nframes * sizeof(jack_default_audio_sample_t));
} else {
jack_ringbuffer_data_t rb_data[2];
jack_ringbuffer_get_read_vector(fRingBuffer, rb_data);
while (nframes_left > 0 && rb_data[0].len > 4) {
jack_nframes_t towrite_frames = (rb_data[0].len) / (sizeof(short) * 2);
towrite_frames = min(towrite_frames, nframes_left);
// write and deinterleave into the two channels
#if 1
sample_move_dS_s16(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2);
sample_move_dS_s16(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2);
#else
sample_move_dS_s16_24ph(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2);
sample_move_dS_s16_24ph(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2);
#endif
wrotebytes = towrite_frames * sizeof(short) * 2;
nframes_left -= towrite_frames;
jack_ringbuffer_read_advance(fRingBuffer, wrotebytes);
jack_ringbuffer_get_read_vector(fRingBuffer, rb_data);
}
if (nframes_left > 0) {
// write silence
memset(outputs[0] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t));
memset(outputs[1] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t));
}
}
return wrotebytes;
}
void JackAC3Encoder::sample_move_dS_s16(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip)
{
/* ALERT: signed sign-extension portability !!! */
while (nsamples--) {
*dst = (*((short *) src)) / SAMPLE_MAX_16BIT;
dst++;
src += src_skip;
}
}
void JackAC3Encoder::sample_move_dS_s16_24ph(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip)
{
/* ALERT: signed sign-extension portability !!! */
while (nsamples--) {
*dst = (((int)(*((short *) src))) << 8) / SAMPLE_MAX_24BIT;
dst++;
src += src_skip;
}
}
void JackAC3Encoder::GetChannelName(char* name, int channel)
{
/*
* 2 channels = L, R
* 3 channels = L, C, R
* 4 channels = L, R, LS, RS
* 5 ch = L, C, R, LS, RS
* 6 ch = L, C, R, LS, RS, LFE
*/
switch (channel) {
case 0:
strcpy(name, "AC3_1_Left");
break;
case 1:
if (fAftenContext.channels == 2 || fAftenContext.channels == 4) {
strcpy(name, "AC3_2_Right");
} else {
strcpy(name, "AC3_2_Center");
}
break;
case 2:
if (fAftenContext.channels == 4) {
strcpy(name, "AC3_3_LeftSurround");
} else {
strcpy(name, "AC3_3_Right");
}
break;
case 3:
if (fAftenContext.channels == 4) {
strcpy(name, "AC3_4_RightSurround");
} else {
strcpy(name, "AC3_4_LeftSurround");
}
break;
case 4:
if (fAftenContext.channels > 4) {
strcpy(name, "AC3_5_RightSurround");
}
break;
default:
break;
}
// Last channel
if (fAftenContext.lfe && (channel == fAftenContext.channels - 1)) {
sprintf(name, "AC3_%d_LFE", fAftenContext.channels + 1);
}
}
} // end of namespace
\ No newline at end of file
/*
Copyright (C) 2006 Jesse Chappell <jesse@essej.net> (AC3Jack)
Copyright (C) 2012 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 __JackAC3Encoder__
#define __JackAC3Encoder__
#include <aften/aften.h>
#include <aften/aften-types.h>
#include "ringbuffer.h"
#include "types.h"
#define MAX_AC3_CHANNELS 6
#define SPDIF_HEADER_SIZE 8
#define SPDIF_FRAME_SIZE 6144
#define SAMPLE_MAX_16BIT 32768.0f
#define SAMPLE_MAX_24BIT 8388608.0f
namespace Jack
{
struct JackAC3EncoderParams
{
int64_t duration;
unsigned int channels;
int bitdepth;
int bitrate;
unsigned int sample_rate;
bool lfe;
};
class JackAC3Encoder
{
private:
AftenContext fAftenContext;
jack_ringbuffer_t* fRingBuffer;
float* fSampleBuffer;
unsigned char* fAC3Buffer;
unsigned char* fZeroBuffer;
int fOutSizeByte;
jack_nframes_t fFramePos;
jack_nframes_t fSampleRate;
jack_nframes_t fByteRate;
void FillSpdifHeader(unsigned char* buf, int outsize);
int Output2Driver(float** outputs, jack_nframes_t nframes);
void sample_move_dS_s16(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip);
void sample_move_dS_s16_24ph(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip);
public:
JackAC3Encoder(const JackAC3EncoderParams& params);
virtual ~JackAC3Encoder();
bool Init(jack_nframes_t sample_rate);
void Process(float** inputs, float** outputs, int nframes);
void GetChannelName(char* name, int channel);
};
typedef JackAC3Encoder * JackAC3EncoderPtr;
} // end of namespace
#endif
......@@ -878,6 +878,10 @@
4BA7BE240DC2350D00AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; };
4BA7BE270DC2352A00AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; };
4BA7FECA0D8E76650017FF73 /* control.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BA7FEC80D8E76650017FF73 /* control.c */; };
4BAA150314F04FB600402512 /* JackAC3Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAA150114F04FB600402512 /* JackAC3Encoder.cpp */; };
4BAA150414F04FB600402512 /* JackAC3Encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BAA150214F04FB600402512 /* JackAC3Encoder.h */; };
4BAA150514F04FB600402512 /* JackAC3Encoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAA150114F04FB600402512 /* JackAC3Encoder.cpp */; };
4BAA150614F04FB600402512 /* JackAC3Encoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BAA150214F04FB600402512 /* JackAC3Encoder.h */; };
4BAB95B80B9E20B800A0C723 /* JackPortType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB95B60B9E20B800A0C723 /* JackPortType.cpp */; };
4BAB95B90B9E20B800A0C723 /* JackPortType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BAB95B70B9E20B800A0C723 /* JackPortType.h */; };
4BAB95BA0B9E20B800A0C723 /* JackPortType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB95B60B9E20B800A0C723 /* JackPortType.cpp */; };
......@@ -1887,6 +1891,8 @@
4BA692D60CBE4CC600EAD520 /* ipunload.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ipunload.c; path = "../example-clients/ipunload.c"; sourceTree = SOURCE_ROOT; };
4BA7FEC30D8E76270017FF73 /* jack_server_control */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_server_control; sourceTree = BUILT_PRODUCTS_DIR; };
4BA7FEC80D8E76650017FF73 /* control.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = control.c; path = "../example-clients/control.c"; sourceTree = SOURCE_ROOT; };
4BAA150114F04FB600402512 /* JackAC3Encoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAC3Encoder.cpp; path = ../common/JackAC3Encoder.cpp; sourceTree = SOURCE_ROOT; };
4BAA150214F04FB600402512 /* JackAC3Encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAC3Encoder.h; path = ../common/JackAC3Encoder.h; sourceTree = SOURCE_ROOT; };
4BAB95B60B9E20B800A0C723 /* JackPortType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackPortType.cpp; path = ../common/JackPortType.cpp; sourceTree = SOURCE_ROOT; };
4BAB95B70B9E20B800A0C723 /* JackPortType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackPortType.h; path = ../common/JackPortType.h; sourceTree = SOURCE_ROOT; };
4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioPort.cpp; path = ../common/JackAudioPort.cpp; sourceTree = SOURCE_ROOT; };
......@@ -3238,8 +3244,8 @@
4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */,
4BF3390D0F8B86AF0080FB5B /* MIDI */,
4B19B3010E23629800DD4A82 /* Adapter */,
BA222AEA0DC88379001A17F4 /* Net */,
4BD56D8707968982006D44F9 /* Threaded */,
BA222AEA0DC88379001A17F4 /* Net */,
4BD56D8607968979006D44F9 /* Audio */,
);
name = Driver;
......@@ -3353,6 +3359,8 @@
4BD56D8607968979006D44F9 /* Audio */ = {
isa = PBXGroup;
children = (
4BAA150114F04FB600402512 /* JackAC3Encoder.cpp */,
4BAA150214F04FB600402512 /* JackAC3Encoder.h */,
4BBB00CF0E72614F0018AB1B /* JackPortAudioDevices.cpp */,
4BBB00D00E72614F0018AB1B /* JackPortAudioDevices.h */,
4BBB00D10E72614F0018AB1B /* JackPortAudioDriver.cpp */,
......@@ -3843,6 +3851,7 @@
buildActionMask = 2147483647;
files = (
4BA4ADB50E87AB2600F26C85 /* JackCoreAudioDriver.h in Headers */,
4BAA150614F04FB600402512 /* JackAC3Encoder.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -4277,6 +4286,7 @@
buildActionMask = 2147483647;
files = (
4BE5FECE0E725C090020B576 /* JackCoreAudioDriver.h in Headers */,
4BAA150414F04FB600402512 /* JackAC3Encoder.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -7381,6 +7391,7 @@
buildActionMask = 2147483647;
files = (
4BA4ADB40E87AB2500F26C85 /* JackCoreAudioDriver.cpp in Sources */,
4BAA150514F04FB600402512 /* JackAC3Encoder.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -7791,6 +7802,7 @@
buildActionMask = 2147483647;
files = (
4BE5FECD0E725C090020B576 /* JackCoreAudioDriver.cpp in Sources */,
4BAA150314F04FB600402512 /* JackAC3Encoder.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -11851,6 +11863,8 @@
"-DJACK_32_64",
);
OTHER_LDFLAGS = (
libaften_pcm.a,
libaften_static.a,
"-framework",
Jackservermp,
"-framework",
......
......@@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackGlobals.h"
#include "JackTools.h"
#include "JackLockedEngine.h"
#include "JackAC3Encoder.h"
#include <sstream>
#include <iostream>
......@@ -323,17 +324,37 @@ int JackCoreAudioDriver::Read()
int JackCoreAudioDriver::Write()
{
for (int i = 0; i < fPlaybackChannels; i++) {
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
// Monitor ports
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
memcpy(GetMonitorBuffer(i), buffer, size);
if (fAC3Encoder) {
// AC3 encoding and SPDIF write
jack_default_audio_sample_t* AC3_inputs[MAX_AC3_CHANNELS];
jack_default_audio_sample_t* AC3_outputs[2];
for (int i = 0; i < fPlaybackChannels; i++) {
AC3_inputs[i] = GetOutputBuffer(i);
// If not connected, clear the buffer
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) == 0) {
memset(AC3_inputs[i], 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
}
}
AC3_outputs[0] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[0].mData;
AC3_outputs[1] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[1].mData;
fAC3Encoder->Process(AC3_inputs, AC3_outputs, fEngineControl->fBufferSize);
} else {
// Standard write
for (int i = 0; i < fPlaybackChannels; i++) {
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
// Monitor ports
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
memcpy(GetMonitorBuffer(i), buffer, size);
}
} else {
memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
}
} else {
memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
}
}
return 0;
......@@ -461,7 +482,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
}
case kAudioDeviceProcessorOverload: {
jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload");
jack_error("DeviceNotificationCallback kAudioDeviceProcessorOverload");
jack_time_t cur_time = GetMicroSeconds();
driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing...
break;
......@@ -688,6 +709,7 @@ OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isIn
JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
: JackAudioDriver(name, alias, engine, table),
fAC3Encoder(NULL),
fJackInputData(NULL),
fDriverOutputData(NULL),
fPluginID(0),
......@@ -699,7 +721,9 @@ JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, Ja
{}
JackCoreAudioDriver::~JackCoreAudioDriver()
{}
{
delete fAC3Encoder;
}
OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
{
......@@ -714,14 +738,14 @@ OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
jack_error("DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
printError(osErr);
return osErr;
}
osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
if (osErr != noErr) {
jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
jack_error("DestroyAggregateDevice : AudioObjectGetPropertyData error");
printError(osErr);
return osErr;
}
......@@ -793,18 +817,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap
for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
jack_error("CreateAggregateDevice : cannot set SR of input device");
} else {
// Check clock domain
osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
if (osErr != 0) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
jack_error("CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
printError(osErr);
} else {
keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
if (clockdomain != 0 && clockdomain != keptclockdomain) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
jack_error("CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
need_clock_drift_compensation = true;
}
}
......@@ -813,18 +837,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap
for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
jack_error("CreateAggregateDevice : cannot set SR of output device");
} else {
// Check clock domain
osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
if (osErr != 0) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
jack_error("CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
printError(osErr);
} else {
keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
if (clockdomain != 0 && clockdomain != keptclockdomain) {
jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");