1 /*
   2  * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 //#define USE_ERROR
  27 //#define USE_TRACE
  28 //#define USE_VERBOSE_TRACE
  29 
  30 #include <AudioUnit/AudioUnit.h>
  31 #include <AudioToolbox/AudioConverter.h>
  32 #include <pthread.h>
  33 #include <math.h>
  34 /*
  35 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
  36 #include <CoreAudio/CoreAudioTypes.h>
  37 #else
  38 #include <CoreAudioTypes.h>
  39 #endif
  40 */
  41 
  42 #include "PLATFORM_API_MacOSX_Utils.h"
  43 
  44 extern "C" {
  45 #include "Utilities.h"
  46 #include "DirectAudio.h"
  47 }
  48 
  49 #if USE_DAUDIO == TRUE
  50 
  51 
  52 #ifdef USE_TRACE
  53 static void PrintStreamDesc(const AudioStreamBasicDescription *inDesc) {
  54     TRACE4("ID='%c%c%c%c'", (char)(inDesc->mFormatID >> 24), (char)(inDesc->mFormatID >> 16), (char)(inDesc->mFormatID >> 8), (char)(inDesc->mFormatID));
  55     TRACE2(", %f Hz, flags=0x%lX", (float)inDesc->mSampleRate, (long unsigned)inDesc->mFormatFlags);
  56     TRACE2(", %ld channels, %ld bits", (long)inDesc->mChannelsPerFrame, (long)inDesc->mBitsPerChannel);
  57     TRACE1(", %ld bytes per frame\n", (long)inDesc->mBytesPerFrame);
  58 }
  59 #else
  60 static inline void PrintStreamDesc(const AudioStreamBasicDescription *inDesc) { }
  61 #endif
  62 
  63 
  64 #define MAX(x, y)   ((x) >= (y) ? (x) : (y))
  65 #define MIN(x, y)   ((x) <= (y) ? (x) : (y))
  66 
  67 
  68 // =======================================
  69 // MixerProvider functions implementation
  70 
  71 static DeviceList deviceCache;
  72 
  73 INT32 DAUDIO_GetDirectAudioDeviceCount() {
  74     deviceCache.Refresh();
  75     int count = deviceCache.GetCount();
  76     if (count > 0) {
  77         // add "default" device
  78         count++;
  79         TRACE1("DAUDIO_GetDirectAudioDeviceCount: returns %d devices\n", count);
  80     } else {
  81         TRACE0("DAUDIO_GetDirectAudioDeviceCount: no devices found\n");
  82     }
  83     return count;
  84 }
  85 
  86 INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription *desc) {
  87     bool result = true;
  88     desc->deviceID = 0;
  89     if (mixerIndex == 0) {
  90         // default device
  91         strncpy(desc->name, "Default Audio Device", DAUDIO_STRING_LENGTH);
  92         strncpy(desc->description, "Default Audio Device", DAUDIO_STRING_LENGTH);
  93         desc->maxSimulLines = -1;
  94     } else {
  95         AudioDeviceID deviceID;
  96         result = deviceCache.GetDeviceInfo(mixerIndex-1, &deviceID, DAUDIO_STRING_LENGTH,
  97             desc->name, desc->vendor, desc->description, desc->version);
  98         if (result) {
  99             desc->deviceID = (INT32)deviceID;
 100             desc->maxSimulLines = -1;
 101         }
 102     }
 103     return result ? TRUE : FALSE;
 104 }
 105 
 106 
 107 void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
 108     TRACE3(">>DAUDIO_GetFormats mixerIndex=%d deviceID=0x%x isSource=%d\n", (int)mixerIndex, (int)deviceID, isSource);
 109 
 110     AudioDeviceID audioDeviceID = deviceID == 0 ? GetDefaultDevice(isSource) : (AudioDeviceID)deviceID;
 111 
 112     if (audioDeviceID == 0) {
 113         return;
 114     }
 115 
 116     int totalChannels = GetChannelCount(audioDeviceID, isSource);
 117 
 118     if (totalChannels == 0) {
 119         TRACE0("<<DAUDIO_GetFormats, no streams!\n");
 120         return;
 121     }
 122 
 123     if (isSource && totalChannels < 2) {
 124         // report 2 channels even if only mono is supported
 125         totalChannels = 2;
 126     }
 127 
 128     int channels[] = {1, 2, totalChannels};
 129     int channelsCount = MIN(totalChannels, 3);
 130 
 131     float hardwareSampleRate = GetSampleRate(audioDeviceID, isSource);
 132     TRACE2("  DAUDIO_GetFormats: got %d channels, sampleRate == %f\n", totalChannels, hardwareSampleRate);
 133 
 134     // any sample rates are supported
 135     float sampleRate = -1;
 136 
 137     static int sampleBits[] = {8, 16, 24};
 138     static int sampleBitsCount = sizeof(sampleBits)/sizeof(sampleBits[0]);
 139 
 140     // the last audio format is the default one (used by DataLine.open() if format is not specified)
 141     // consider as default 16bit PCM stereo (mono is stereo is not supported) with the current sample rate
 142     int defBits = 16;
 143     int defChannels = MIN(2, channelsCount);
 144     float defSampleRate = hardwareSampleRate;
 145     // don't add default format is sample rate is not specified
 146     bool addDefault = defSampleRate > 0;
 147 
 148     // TODO: CoreAudio can handle signed/unsigned, little-endian/big-endian
 149     // TODO: register the formats (to prevent DirectAudio software conversion) - need to fix DirectAudioDevice.createDataLineInfo
 150     // to avoid software conversions if both signed/unsigned or big-/little-endian are supported
 151     for (int channelIndex = 0; channelIndex < channelsCount; channelIndex++) {
 152         for (int bitIndex = 0; bitIndex < sampleBitsCount; bitIndex++) {
 153             int bits = sampleBits[bitIndex];
 154             if (addDefault && bits == defBits && channels[channelIndex] != defChannels && sampleRate == defSampleRate) {
 155                 // the format is the default one, don't add it now
 156                 continue;
 157             }
 158             DAUDIO_AddAudioFormat(creator,
 159                 bits,                       // sample size in bits
 160                 -1,                         // frame size (auto)
 161                 channels[channelIndex],     // channels
 162                 sampleRate,                 // sample rate
 163                 DAUDIO_PCM,                 // only accept PCM
 164                 bits == 8 ? FALSE : TRUE,   // signed
 165                 bits == 8 ? FALSE           // little-endian for 8bit
 166                     : UTIL_IsBigEndianPlatform());
 167         }
 168     }
 169     // add default format
 170     if (addDefault) {
 171         DAUDIO_AddAudioFormat(creator,
 172             defBits,                        // 16 bits
 173             -1,                             // automatically calculate frame size
 174             defChannels,                    // channels
 175             defSampleRate,                  // sample rate
 176             DAUDIO_PCM,                     // PCM
 177             TRUE,                           // signed
 178             UTIL_IsBigEndianPlatform());    // native endianess
 179     }
 180 
 181     TRACE0("<<DAUDIO_GetFormats\n");
 182 }
 183 
 184 
 185 // =======================================
 186 // Source/Target DataLine functions implementation
 187 
 188 // ====
 189 /* 1writer-1reader ring buffer class with flush() support */
 190 class RingBuffer {
 191 public:
 192     RingBuffer() : pBuffer(NULL), nBufferSize(0) {
 193         pthread_mutex_init(&lockMutex, NULL);
 194     }
 195     ~RingBuffer() {
 196         Deallocate();
 197         pthread_mutex_destroy(&lockMutex);
 198     }
 199 
 200     // extraBytes: number of additionally allocated bytes to prevent data
 201     // overlapping when almost whole buffer is filled
 202     // (required only if Write() can override the buffer)
 203     bool Allocate(int requestedBufferSize, int extraBytes) {
 204         int fullBufferSize = requestedBufferSize + extraBytes;
 205         int powerOfTwo = 1;
 206         while (powerOfTwo < fullBufferSize) {
 207             powerOfTwo <<= 1;
 208         }
 209         pBuffer = (Byte*)malloc(powerOfTwo);
 210         if (pBuffer == NULL) {
 211             ERROR0("RingBuffer::Allocate: OUT OF MEMORY\n");
 212             return false;
 213         }
 214 
 215         nBufferSize = requestedBufferSize;
 216         nAllocatedBytes = powerOfTwo;
 217         nPosMask = powerOfTwo - 1;
 218         nWritePos = 0;
 219         nReadPos = 0;
 220         nFlushPos = -1;
 221 
 222         TRACE2("RingBuffer::Allocate: OK, bufferSize=%d, allocated:%d\n", nBufferSize, nAllocatedBytes);
 223         return true;
 224     }
 225 
 226     void Deallocate() {
 227         if (pBuffer) {
 228             free(pBuffer);
 229             pBuffer = NULL;
 230             nBufferSize = 0;
 231         }
 232     }
 233 
 234     inline int GetBufferSize() {
 235         return nBufferSize;
 236     }
 237 
 238     inline int GetAllocatedSize() {
 239         return nAllocatedBytes;
 240     }
 241 
 242     // gets number of bytes available for reading
 243     int GetValidByteCount() {
 244         lock();
 245         INT64 result = nWritePos - (nFlushPos >= 0 ? nFlushPos : nReadPos);
 246         unlock();
 247         return result > (INT64)nBufferSize ? nBufferSize : (int)result;
 248     }
 249 
 250     int Write(void *srcBuffer, int len, bool preventOverflow) {
 251         lock();
 252         TRACE2("RingBuffer::Write (%d bytes, preventOverflow=%d)\n", len, preventOverflow ? 1 : 0);
 253         TRACE2("  writePos = %lld (%d)", (long long)nWritePos, Pos2Offset(nWritePos));
 254         TRACE2("  readPos=%lld (%d)", (long long)nReadPos, Pos2Offset(nReadPos));
 255         TRACE2("  flushPos=%lld (%d)\n", (long long)nFlushPos, Pos2Offset(nFlushPos));
 256 
 257         INT64 writePos = nWritePos;
 258         if (preventOverflow) {
 259             INT64 avail_read = writePos - (nFlushPos >= 0 ? nFlushPos : nReadPos);
 260             if (avail_read >= (INT64)nBufferSize) {
 261                 // no space
 262                 TRACE0("  preventOverlow: OVERFLOW => len = 0;\n");
 263                 len = 0;
 264             } else {
 265                 int avail_write = nBufferSize - (int)avail_read;
 266                 if (len > avail_write) {
 267                     TRACE2("  preventOverlow: desrease len: %d => %d\n", len, avail_write);
 268                     len = avail_write;
 269                 }
 270             }
 271         }
 272         unlock();
 273 
 274         if (len > 0) {
 275 
 276             write((Byte *)srcBuffer, Pos2Offset(writePos), len);
 277 
 278             lock();
 279             TRACE4("--RingBuffer::Write writePos: %lld (%d) => %lld, (%d)\n",
 280                 (long long)nWritePos, Pos2Offset(nWritePos), (long long)nWritePos + len, Pos2Offset(nWritePos + len));
 281             nWritePos += len;
 282             unlock();
 283         }
 284         return len;
 285     }
 286 
 287     int Read(void *dstBuffer, int len) {
 288         lock();
 289         TRACE1("RingBuffer::Read (%d bytes)\n", len);
 290         TRACE2("  writePos = %lld (%d)", (long long)nWritePos, Pos2Offset(nWritePos));
 291         TRACE2("  readPos=%lld (%d)", (long long)nReadPos, Pos2Offset(nReadPos));
 292         TRACE2("  flushPos=%lld (%d)\n", (long long)nFlushPos, Pos2Offset(nFlushPos));
 293 
 294         applyFlush();
 295         INT64 avail_read = nWritePos - nReadPos;
 296         // check for overflow
 297         if (avail_read > (INT64)nBufferSize) {
 298             nReadPos = nWritePos - nBufferSize;
 299             avail_read = nBufferSize;
 300             TRACE0("  OVERFLOW\n");
 301         }
 302         INT64 readPos = nReadPos;
 303         unlock();
 304 
 305         if (len > (int)avail_read) {
 306             TRACE2("  RingBuffer::Read - don't have enough data, len: %d => %d\n", len, (int)avail_read);
 307             len = (int)avail_read;
 308         }
 309 
 310         if (len > 0) {
 311 
 312             read((Byte *)dstBuffer, Pos2Offset(readPos), len);
 313 
 314             lock();
 315             if (applyFlush()) {
 316                 // just got flush(), results became obsolete
 317                 TRACE0("--RingBuffer::Read, got Flush, return 0\n");
 318                 len = 0;
 319             } else {
 320                 TRACE4("--RingBuffer::Read readPos: %lld (%d) => %lld (%d)\n",
 321                     (long long)nReadPos, Pos2Offset(nReadPos), (long long)nReadPos + len, Pos2Offset(nReadPos + len));
 322                 nReadPos += len;
 323             }
 324             unlock();
 325         } else {
 326             // underrun!
 327         }
 328         return len;
 329     }
 330 
 331     // returns number of the flushed bytes
 332     int Flush() {
 333         lock();
 334         INT64 flushedBytes = nWritePos - (nFlushPos >= 0 ? nFlushPos : nReadPos);
 335         nFlushPos = nWritePos;
 336         unlock();
 337         return flushedBytes > (INT64)nBufferSize ? nBufferSize : (int)flushedBytes;
 338     }
 339 
 340 private:
 341     Byte *pBuffer;
 342     int nBufferSize;
 343     int nAllocatedBytes;
 344     INT64 nPosMask;
 345 
 346     pthread_mutex_t lockMutex;
 347 
 348     volatile INT64 nWritePos;
 349     volatile INT64 nReadPos;
 350     // Flush() sets nFlushPos value to nWritePos;
 351     // next Read() sets nReadPos to nFlushPos and resests nFlushPos to -1
 352     volatile INT64 nFlushPos;
 353 
 354     inline void lock() {
 355         pthread_mutex_lock(&lockMutex);
 356     }
 357     inline void unlock() {
 358         pthread_mutex_unlock(&lockMutex);
 359     }
 360 
 361     inline bool applyFlush() {
 362         if (nFlushPos >= 0) {
 363             nReadPos = nFlushPos;
 364             nFlushPos = -1;
 365             return true;
 366         }
 367         return false;
 368     }
 369 
 370     inline int Pos2Offset(INT64 pos) {
 371         return (int)(pos & nPosMask);
 372     }
 373 
 374     void write(Byte *srcBuffer, int dstOffset, int len) {
 375         int dstEndOffset = dstOffset + len;
 376 
 377         int lenAfterWrap = dstEndOffset - nAllocatedBytes;
 378         if (lenAfterWrap > 0) {
 379             // dest.buffer does wrap
 380             len = nAllocatedBytes - dstOffset;
 381             memcpy(pBuffer+dstOffset, srcBuffer, len);
 382             memcpy(pBuffer, srcBuffer+len, lenAfterWrap);
 383         } else {
 384             // dest.buffer does not wrap
 385             memcpy(pBuffer+dstOffset, srcBuffer, len);
 386         }
 387     }
 388 
 389     void read(Byte *dstBuffer, int srcOffset, int len) {
 390         int srcEndOffset = srcOffset + len;
 391 
 392         int lenAfterWrap = srcEndOffset - nAllocatedBytes;
 393         if (lenAfterWrap > 0) {
 394             // need to unwrap data
 395             len = nAllocatedBytes - srcOffset;
 396             memcpy(dstBuffer, pBuffer+srcOffset, len);
 397             memcpy(dstBuffer+len, pBuffer, lenAfterWrap);
 398         } else {
 399             // source buffer is not wrapped
 400             memcpy(dstBuffer, pBuffer+srcOffset, len);
 401         }
 402     }
 403 };
 404 
 405 
 406 class Resampler {
 407 private:
 408     enum {
 409         kResamplerEndOfInputData = 1 // error to interrupt conversion (end of input data)
 410     };
 411 public:
 412     Resampler() : converter(NULL), outBuffer(NULL) { }
 413     ~Resampler() {
 414         if (converter != NULL) {
 415             AudioConverterDispose(converter);
 416         }
 417         if (outBuffer != NULL) {
 418             free(outBuffer);
 419         }
 420     }
 421 
 422     // inFormat & outFormat must be interleaved!
 423     bool Init(const AudioStreamBasicDescription *inFormat, const AudioStreamBasicDescription *outFormat,
 424             int inputBufferSizeInBytes)
 425     {
 426         TRACE0(">>Resampler::Init\n");
 427         TRACE0("  inFormat: ");
 428         PrintStreamDesc(inFormat);
 429         TRACE0("  outFormat: ");
 430         PrintStreamDesc(outFormat);
 431         TRACE1("  inputBufferSize: %d bytes\n", inputBufferSizeInBytes);
 432         OSStatus err;
 433 
 434         if ((outFormat->mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0 && outFormat->mChannelsPerFrame != 1) {
 435             ERROR0("Resampler::Init ERROR: outFormat is non-interleaved\n");
 436             return false;
 437         }
 438         if ((inFormat->mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0 && inFormat->mChannelsPerFrame != 1) {
 439             ERROR0("Resampler::Init ERROR: inFormat is non-interleaved\n");
 440             return false;
 441         }
 442 
 443         memcpy(&asbdIn, inFormat, sizeof(AudioStreamBasicDescription));
 444         memcpy(&asbdOut, outFormat, sizeof(AudioStreamBasicDescription));
 445 
 446         err = AudioConverterNew(inFormat, outFormat, &converter);
 447 
 448         if (err || converter == NULL) {
 449             OS_ERROR1(err, "Resampler::Init (AudioConverterNew), converter=%p", converter);
 450             return false;
 451         }
 452 
 453         // allocate buffer for output data
 454         int maximumInFrames = inputBufferSizeInBytes / inFormat->mBytesPerFrame;
 455         // take into account trailingFrames
 456         AudioConverterPrimeInfo primeInfo = {0, 0};
 457         UInt32 sizePrime = sizeof(primeInfo);
 458         err = AudioConverterGetProperty(converter, kAudioConverterPrimeInfo, &sizePrime, &primeInfo);
 459         if (err) {
 460             OS_ERROR0(err, "Resampler::Init (get kAudioConverterPrimeInfo)");
 461             // ignore the error
 462         } else {
 463             // the default primeMethod is kConverterPrimeMethod_Normal, so we need only trailingFrames
 464             maximumInFrames += primeInfo.trailingFrames;
 465         }
 466         float outBufferSizeInFrames = (outFormat->mSampleRate / inFormat->mSampleRate) * ((float)maximumInFrames);
 467         // to avoid complex calculation just set outBufferSize as double of the calculated value
 468         outBufferSize = (int)outBufferSizeInFrames * outFormat->mBytesPerFrame * 2;
 469         // safety check - consider 256 frame as the minimum input buffer
 470         int minOutSize = 256 * outFormat->mBytesPerFrame;
 471         if (outBufferSize < minOutSize) {
 472             outBufferSize = minOutSize;
 473         }
 474 
 475         outBuffer = malloc(outBufferSize);
 476 
 477         if (outBuffer == NULL) {
 478             ERROR1("Resampler::Init ERROR: malloc failed (%d bytes)\n", outBufferSize);
 479             AudioConverterDispose(converter);
 480             converter = NULL;
 481             return false;
 482         }
 483 
 484         TRACE1("  allocated: %d bytes for output buffer\n", outBufferSize);
 485 
 486         TRACE0("<<Resampler::Init: OK\n");
 487         return true;
 488     }
 489 
 490     // returns size of the internal output buffer
 491     int GetOutBufferSize() {
 492         return outBufferSize;
 493     }
 494 
 495     // process next part of data (writes resampled data to the ringBuffer without overflow check)
 496     int Process(void *srcBuffer, int len, RingBuffer *ringBuffer) {
 497         int bytesWritten = 0;
 498         TRACE2(">>Resampler::Process: %d bytes, converter = %p\n", len, converter);
 499         if (converter == NULL) {    // sanity check
 500             bytesWritten = ringBuffer->Write(srcBuffer, len, false);
 501         } else {
 502             InputProcData data;
 503             data.pThis = this;
 504             data.data = (Byte *)srcBuffer;
 505             data.dataSize = len;
 506 
 507             OSStatus err;
 508             do {
 509                 AudioBufferList abl;    // by default it contains 1 AudioBuffer
 510                 abl.mNumberBuffers = 1;
 511                 abl.mBuffers[0].mNumberChannels = asbdOut.mChannelsPerFrame;
 512                 abl.mBuffers[0].mDataByteSize   = outBufferSize;
 513                 abl.mBuffers[0].mData           = outBuffer;
 514 
 515                 UInt32 packets = (UInt32)outBufferSize / asbdOut.mBytesPerPacket;
 516 
 517                 TRACE2(">>AudioConverterFillComplexBuffer: request %d packets, provide %d bytes buffer\n",
 518                     (int)packets, (int)abl.mBuffers[0].mDataByteSize);
 519 
 520                 err = AudioConverterFillComplexBuffer(converter, ConverterInputProc, &data, &packets, &abl, NULL);
 521 
 522                 TRACE2("<<AudioConverterFillComplexBuffer: got %d packets (%d bytes)\n",
 523                     (int)packets, (int)abl.mBuffers[0].mDataByteSize);
 524                 if (packets > 0) {
 525                     int bytesToWrite = (int)(packets * asbdOut.mBytesPerPacket);
 526                     bytesWritten += ringBuffer->Write(abl.mBuffers[0].mData, bytesToWrite, false);
 527                 }
 528 
 529                 // if outputBuffer is small to store all available frames,
 530                 // we get noErr here. In the case just continue the conversion
 531             } while (err == noErr);
 532 
 533             if (err != kResamplerEndOfInputData) {
 534                 // unexpected error
 535                 OS_ERROR0(err, "Resampler::Process (AudioConverterFillComplexBuffer)");
 536             }
 537         }
 538         TRACE2("<<Resampler::Process: written %d bytes (converted from %d bytes)\n", bytesWritten, len);
 539 
 540         return bytesWritten;
 541     }
 542 
 543     // resets internal bufferes
 544     void Discontinue() {
 545         TRACE0(">>Resampler::Discontinue\n");
 546         if (converter != NULL) {
 547             AudioConverterReset(converter);
 548         }
 549         TRACE0("<<Resampler::Discontinue\n");
 550     }
 551 
 552 private:
 553     AudioConverterRef converter;
 554 
 555     // buffer for output data
 556     // note that there is no problem if the buffer is not big enough to store
 557     // all converted data - it's only performance issue
 558     void *outBuffer;
 559     int outBufferSize;
 560 
 561     AudioStreamBasicDescription asbdIn;
 562     AudioStreamBasicDescription asbdOut;
 563 
 564     struct InputProcData {
 565         Resampler *pThis;
 566         Byte *data;     // data == NULL means we handle Discontinue(false)
 567         int dataSize;   // == 0 if all data was already provided to the converted of we handle Discontinue(false)
 568     };
 569 
 570     static OSStatus ConverterInputProc(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets,
 571             AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData)
 572     {
 573         InputProcData *data = (InputProcData *)inUserData;
 574 
 575         TRACE3("  >>ConverterInputProc: requested %d packets, data contains %d bytes (%d packets)\n",
 576             (int)*ioNumberDataPackets, (int)data->dataSize, (int)(data->dataSize / data->pThis->asbdIn.mBytesPerPacket));
 577         if (data->dataSize == 0) {
 578             // already called & provided all input data
 579             // interrupt conversion by returning error
 580             *ioNumberDataPackets = 0;
 581             TRACE0("  <<ConverterInputProc: returns kResamplerEndOfInputData\n");
 582             return kResamplerEndOfInputData;
 583         }
 584 
 585         ioData->mNumberBuffers = 1;
 586         ioData->mBuffers[0].mNumberChannels = data->pThis->asbdIn.mChannelsPerFrame;
 587         ioData->mBuffers[0].mDataByteSize   = data->dataSize;
 588         ioData->mBuffers[0].mData           = data->data;
 589 
 590         *ioNumberDataPackets = data->dataSize / data->pThis->asbdIn.mBytesPerPacket;
 591 
 592         // all data has been provided to the converter
 593         data->dataSize = 0;
 594 
 595         TRACE1("  <<ConverterInputProc: returns %d packets\n", (int)(*ioNumberDataPackets));
 596         return noErr;
 597     }
 598 
 599 };
 600 
 601 
 602 struct OSX_DirectAudioDevice {
 603     AudioUnit   audioUnit;
 604     RingBuffer  ringBuffer;
 605     AudioStreamBasicDescription asbd;
 606 
 607     // only for target lines
 608     UInt32      inputBufferSizeInBytes;
 609     Resampler   *resampler;
 610     // to detect discontinuity (to reset resampler)
 611     SInt64      lastWrittenSampleTime;
 612 
 613 
 614     OSX_DirectAudioDevice() : audioUnit(NULL), asbd(), resampler(NULL), lastWrittenSampleTime(0) {
 615     }
 616 
 617     ~OSX_DirectAudioDevice() {
 618         if (audioUnit) {
 619             AudioComponentInstanceDispose(audioUnit);
 620         }
 621         if (resampler) {
 622             delete resampler;
 623         }
 624     }
 625 };
 626 
 627 static AudioUnit CreateOutputUnit(AudioDeviceID deviceID, int isSource)
 628 {
 629     OSStatus err;
 630     AudioUnit unit;
 631 
 632     AudioComponentDescription desc;
 633     desc.componentType         = kAudioUnitType_Output;
 634     desc.componentSubType      = (deviceID == 0 && isSource) ? kAudioUnitSubType_DefaultOutput : kAudioUnitSubType_HALOutput;
 635     desc.componentManufacturer = kAudioUnitManufacturer_Apple;
 636     desc.componentFlags        = 0;
 637     desc.componentFlagsMask    = 0;
 638 
 639     AudioComponent comp = AudioComponentFindNext(NULL, &desc);
 640     err = AudioComponentInstanceNew(comp, &unit);
 641 
 642     if (err) {
 643         OS_ERROR0(err, "CreateOutputUnit:OpenAComponent");
 644         return NULL;
 645     }
 646 
 647     if (!isSource) {
 648         int enableIO = 0;
 649         err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output,
 650                                     0, &enableIO, sizeof(enableIO));
 651         if (err) {
 652             OS_ERROR0(err, "SetProperty (output EnableIO)");
 653         }
 654         enableIO = 1;
 655         err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input,
 656                                     1, &enableIO, sizeof(enableIO));
 657         if (err) {
 658             OS_ERROR0(err, "SetProperty (input EnableIO)");
 659         }
 660 
 661         if (!deviceID) {
 662             // get real AudioDeviceID for default input device (macosx current input device)
 663             deviceID = GetDefaultDevice(isSource);
 664             if (!deviceID) {
 665                 AudioComponentInstanceDispose(unit);
 666                 return NULL;
 667             }
 668         }
 669     }
 670 
 671     if (deviceID) {
 672         err = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global,
 673                                     0, &deviceID, sizeof(deviceID));
 674         if (err) {
 675             OS_ERROR0(err, "SetProperty (CurrentDevice)");
 676             AudioComponentInstanceDispose(unit);
 677             return NULL;
 678         }
 679     }
 680 
 681     return unit;
 682 }
 683 
 684 static OSStatus OutputCallback(void                         *inRefCon,
 685                                AudioUnitRenderActionFlags   *ioActionFlags,
 686                                const AudioTimeStamp         *inTimeStamp,
 687                                UInt32                       inBusNumber,
 688                                UInt32                       inNumberFrames,
 689                                AudioBufferList              *ioData)
 690 {
 691     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)inRefCon;
 692 
 693     int nchannels = ioData->mNumberBuffers; // should be always == 1 (interleaved channels)
 694     AudioBuffer *audioBuffer = ioData->mBuffers;
 695 
 696     TRACE3(">>OutputCallback: busNum=%d, requested %d frames (%d bytes)\n",
 697         (int)inBusNumber, (int)inNumberFrames, (int)(inNumberFrames * device->asbd.mBytesPerFrame));
 698     TRACE3("  abl: %d buffers, buffer[0].channels=%d, buffer.size=%d\n",
 699         nchannels, (int)audioBuffer->mNumberChannels, (int)audioBuffer->mDataByteSize);
 700 
 701     int bytesToRead = inNumberFrames * device->asbd.mBytesPerFrame;
 702     if (bytesToRead > (int)audioBuffer->mDataByteSize) {
 703         TRACE0("--OutputCallback: !!! audioBuffer IS TOO SMALL!!!\n");
 704         bytesToRead = audioBuffer->mDataByteSize / device->asbd.mBytesPerFrame * device->asbd.mBytesPerFrame;
 705     }
 706     int bytesRead = device->ringBuffer.Read(audioBuffer->mData, bytesToRead);
 707     if (bytesRead < bytesToRead) {
 708         // no enough data (underrun)
 709         TRACE2("--OutputCallback: !!! UNDERRUN (read %d bytes of %d)!!!\n", bytesRead, bytesToRead);
 710         // silence the rest
 711         memset((Byte*)audioBuffer->mData + bytesRead, 0, bytesToRead-bytesRead);
 712         bytesRead = bytesToRead;
 713     }
 714 
 715     audioBuffer->mDataByteSize = (UInt32)bytesRead;
 716     // SAFETY: set mDataByteSize for all other AudioBuffer in the AudioBufferList to zero
 717     while (--nchannels > 0) {
 718         audioBuffer++;
 719         audioBuffer->mDataByteSize = 0;
 720     }
 721     TRACE1("<<OutputCallback (returns %d)\n", bytesRead);
 722 
 723     return noErr;
 724 }
 725 
 726 static OSStatus InputCallback(void                          *inRefCon,
 727                               AudioUnitRenderActionFlags    *ioActionFlags,
 728                               const AudioTimeStamp          *inTimeStamp,
 729                               UInt32                        inBusNumber,
 730                               UInt32                        inNumberFrames,
 731                               AudioBufferList               *ioData)
 732 {
 733     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)inRefCon;
 734 
 735     TRACE4(">>InputCallback: busNum=%d, timeStamp=%lld, %d frames (%d bytes)\n",
 736         (int)inBusNumber, (long long)inTimeStamp->mSampleTime, (int)inNumberFrames, (int)(inNumberFrames * device->asbd.mBytesPerFrame));
 737 
 738     AudioBufferList abl;    // by default it contains 1 AudioBuffer
 739     abl.mNumberBuffers = 1;
 740     abl.mBuffers[0].mNumberChannels = device->asbd.mChannelsPerFrame;
 741     abl.mBuffers[0].mDataByteSize   = device->inputBufferSizeInBytes;   // assume this is == (inNumberFrames * device->asbd.mBytesPerFrame)
 742     abl.mBuffers[0].mData           = NULL;     // request for the audioUnit's buffer
 743 
 744     OSStatus err = AudioUnitRender(device->audioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &abl);
 745     if (err) {
 746         OS_ERROR0(err, "<<InputCallback: AudioUnitRender");
 747     } else {
 748         if (device->resampler != NULL) {
 749             // test for discontinuity
 750             // AUHAL starts timestamps at zero, so test if the current timestamp less then the last written
 751             SInt64 sampleTime = inTimeStamp->mSampleTime;
 752             if (sampleTime < device->lastWrittenSampleTime) {
 753                 // discontinuity, reset the resampler
 754                 TRACE2("  InputCallback (RESAMPLED), DISCONTINUITY (%f -> %f)\n",
 755                     (float)device->lastWrittenSampleTime, (float)sampleTime);
 756 
 757                 device->resampler->Discontinue();
 758             } else {
 759                 TRACE2("  InputCallback (RESAMPLED), continuous: lastWrittenSampleTime = %f, sampleTime=%f\n",
 760                     (float)device->lastWrittenSampleTime, (float)sampleTime);
 761             }
 762             device->lastWrittenSampleTime = sampleTime + inNumberFrames;
 763 
 764             int bytesWritten = device->resampler->Process(abl.mBuffers[0].mData, (int)abl.mBuffers[0].mDataByteSize, &device->ringBuffer);
 765             TRACE2("<<InputCallback (RESAMPLED, saved %d bytes of %d)\n", bytesWritten, (int)abl.mBuffers[0].mDataByteSize);
 766         } else {
 767             int bytesWritten = device->ringBuffer.Write(abl.mBuffers[0].mData, (int)abl.mBuffers[0].mDataByteSize, false);
 768             TRACE2("<<InputCallback (saved %d bytes of %d)\n", bytesWritten, (int)abl.mBuffers[0].mDataByteSize);
 769         }
 770     }
 771 
 772     return noErr;
 773 }
 774 
 775 
 776 static void FillASBDForNonInterleavedPCM(AudioStreamBasicDescription& asbd,
 777     float sampleRate, int channels, int sampleSizeInBits, bool isFloat, int isSigned, bool isBigEndian)
 778 {
 779     // FillOutASBDForLPCM cannot produce unsigned integer format
 780     asbd.mSampleRate = sampleRate;
 781     asbd.mFormatID = kAudioFormatLinearPCM;
 782     asbd.mFormatFlags = (isFloat ? kAudioFormatFlagIsFloat : (isSigned ? kAudioFormatFlagIsSignedInteger : 0))
 783         | (isBigEndian ? (kAudioFormatFlagIsBigEndian) : 0)
 784         | kAudioFormatFlagIsPacked;
 785     asbd.mBytesPerPacket = channels * ((sampleSizeInBits + 7) / 8);
 786     asbd.mFramesPerPacket = 1;
 787     asbd.mBytesPerFrame = asbd.mBytesPerPacket;
 788     asbd.mChannelsPerFrame = channels;
 789     asbd.mBitsPerChannel = sampleSizeInBits;
 790 }
 791 
 792 void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
 793                   int encoding, float sampleRate, int sampleSizeInBits,
 794                   int frameSize, int channels,
 795                   int isSigned, int isBigEndian, int bufferSizeInBytes)
 796 {
 797     TRACE3(">>DAUDIO_Open: mixerIndex=%d deviceID=0x%x isSource=%d\n", (int)mixerIndex, (unsigned int)deviceID, isSource);
 798     TRACE3("  sampleRate=%d sampleSizeInBits=%d channels=%d\n", (int)sampleRate, sampleSizeInBits, channels);
 799 #ifdef USE_TRACE
 800     {
 801         AudioDeviceID audioDeviceID = deviceID;
 802         if (audioDeviceID == 0) {
 803             // default device
 804             audioDeviceID = GetDefaultDevice(isSource);
 805         }
 806         char name[256];
 807         OSStatus err = GetAudioObjectProperty(audioDeviceID, kAudioUnitScope_Global, kAudioDevicePropertyDeviceName, 256, &name, 0);
 808         if (err != noErr) {
 809             OS_ERROR1(err, "  audioDeviceID=0x%x, name is N/A:", (int)audioDeviceID);
 810         } else {
 811             TRACE2("  audioDeviceID=0x%x, name=%s\n", (int)audioDeviceID, name);
 812         }
 813     }
 814 #endif
 815 
 816     if (encoding != DAUDIO_PCM) {
 817         ERROR1("<<DAUDIO_Open: ERROR: unsupported encoding (%d)\n", encoding);
 818         return NULL;
 819     }
 820 
 821     OSX_DirectAudioDevice *device = new OSX_DirectAudioDevice();
 822 
 823     AudioUnitScope scope = isSource ? kAudioUnitScope_Input : kAudioUnitScope_Output;
 824     int element = isSource ? 0 : 1;
 825     OSStatus err = noErr;
 826     int extraBufferBytes = 0;
 827 
 828     device->audioUnit = CreateOutputUnit(deviceID, isSource);
 829 
 830     if (!device->audioUnit) {
 831         delete device;
 832         return NULL;
 833     }
 834 
 835     if (!isSource) {
 836         AudioDeviceID actualDeviceID = deviceID != 0 ? deviceID : GetDefaultDevice(isSource);
 837         float hardwareSampleRate = GetSampleRate(actualDeviceID, isSource);
 838         TRACE2("--DAUDIO_Open: sampleRate = %f, hardwareSampleRate=%f\n", sampleRate, hardwareSampleRate);
 839 
 840         if (fabs(sampleRate - hardwareSampleRate) > 1) {
 841             device->resampler = new Resampler();
 842 
 843             // request HAL for Float32 with native endianess
 844             FillASBDForNonInterleavedPCM(device->asbd, hardwareSampleRate, channels, 32, true, false, kAudioFormatFlagsNativeEndian != 0);
 845         } else {
 846             sampleRate = hardwareSampleRate;    // in case sample rates are not exactly equal
 847         }
 848     }
 849 
 850     if (device->resampler == NULL) {
 851         // no resampling, request HAL for the requested format
 852         FillASBDForNonInterleavedPCM(device->asbd, sampleRate, channels, sampleSizeInBits, false, isSigned, isBigEndian);
 853     }
 854 
 855     err = AudioUnitSetProperty(device->audioUnit, kAudioUnitProperty_StreamFormat, scope, element, &device->asbd, sizeof(device->asbd));
 856     if (err) {
 857         OS_ERROR0(err, "<<DAUDIO_Open set StreamFormat");
 858         delete device;
 859         return NULL;
 860     }
 861 
 862     AURenderCallbackStruct output;
 863     output.inputProc       = isSource ? OutputCallback : InputCallback;
 864     output.inputProcRefCon = device;
 865 
 866     err = AudioUnitSetProperty(device->audioUnit,
 867                                 isSource
 868                                     ? (AudioUnitPropertyID)kAudioUnitProperty_SetRenderCallback
 869                                     : (AudioUnitPropertyID)kAudioOutputUnitProperty_SetInputCallback,
 870                                 kAudioUnitScope_Global, 0, &output, sizeof(output));
 871     if (err) {
 872         OS_ERROR0(err, "<<DAUDIO_Open set RenderCallback");
 873         delete device;
 874         return NULL;
 875     }
 876 
 877     err = AudioUnitInitialize(device->audioUnit);
 878     if (err) {
 879         OS_ERROR0(err, "<<DAUDIO_Open UnitInitialize");
 880         delete device;
 881         return NULL;
 882     }
 883 
 884     if (!isSource) {
 885         // for target lines we need extra bytes in the ringBuffer
 886         // to prevent collisions when InputCallback overrides data on overflow
 887         UInt32 size;
 888         OSStatus err;
 889 
 890         size = sizeof(device->inputBufferSizeInBytes);
 891         err  = AudioUnitGetProperty(device->audioUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global,
 892                                     0, &device->inputBufferSizeInBytes, &size);
 893         if (err) {
 894             OS_ERROR0(err, "<<DAUDIO_Open (TargetDataLine)GetBufferSize\n");
 895             delete device;
 896             return NULL;
 897         }
 898         device->inputBufferSizeInBytes *= device->asbd.mBytesPerFrame;  // convert frames to bytes
 899         extraBufferBytes = (int)device->inputBufferSizeInBytes;
 900     }
 901 
 902     if (device->resampler != NULL) {
 903         // resampler output format is a user requested format (== ringBuffer format)
 904         AudioStreamBasicDescription asbdOut; // ringBuffer format
 905         FillASBDForNonInterleavedPCM(asbdOut, sampleRate, channels, sampleSizeInBits, false, isSigned, isBigEndian);
 906 
 907         // set resampler input buffer size to the HAL buffer size
 908         if (!device->resampler->Init(&device->asbd, &asbdOut, (int)device->inputBufferSizeInBytes)) {
 909             ERROR0("<<DAUDIO_Open: resampler.Init() FAILED.\n");
 910             delete device;
 911             return NULL;
 912         }
 913         // extra bytes in the ringBuffer (extraBufferBytes) should be equal resampler output buffer size
 914         extraBufferBytes = device->resampler->GetOutBufferSize();
 915     }
 916 
 917     if (!device->ringBuffer.Allocate(bufferSizeInBytes, extraBufferBytes)) {
 918         ERROR0("<<DAUDIO_Open: Ring buffer allocation error\n");
 919         delete device;
 920         return NULL;
 921     }
 922 
 923     TRACE0("<<DAUDIO_Open: OK\n");
 924     return device;
 925 }
 926 
 927 int DAUDIO_Start(void* id, int isSource) {
 928     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 929     TRACE0("DAUDIO_Start\n");
 930 
 931     OSStatus err = AudioOutputUnitStart(device->audioUnit);
 932 
 933     if (err != noErr) {
 934         OS_ERROR0(err, "DAUDIO_Start");
 935     }
 936 
 937     return err == noErr ? TRUE : FALSE;
 938 }
 939 
 940 int DAUDIO_Stop(void* id, int isSource) {
 941     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 942     TRACE0("DAUDIO_Stop\n");
 943 
 944     OSStatus err = AudioOutputUnitStop(device->audioUnit);
 945 
 946     return err == noErr ? TRUE : FALSE;
 947 }
 948 
 949 void DAUDIO_Close(void* id, int isSource) {
 950     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 951     TRACE0("DAUDIO_Close\n");
 952 
 953     delete device;
 954 }
 955 
 956 int DAUDIO_Write(void* id, char* data, int byteSize) {
 957     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 958     TRACE1(">>DAUDIO_Write: %d bytes to write\n", byteSize);
 959 
 960     int result = device->ringBuffer.Write(data, byteSize, true);
 961 
 962     TRACE1("<<DAUDIO_Write: %d bytes written\n", result);
 963     return result;
 964 }
 965 
 966 int DAUDIO_Read(void* id, char* data, int byteSize) {
 967     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 968     TRACE1(">>DAUDIO_Read: %d bytes to read\n", byteSize);
 969 
 970     int result = device->ringBuffer.Read(data, byteSize);
 971 
 972     TRACE1("<<DAUDIO_Read: %d bytes has been read\n", result);
 973     return result;
 974 }
 975 
 976 int DAUDIO_GetBufferSize(void* id, int isSource) {
 977     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 978 
 979     int bufferSizeInBytes = device->ringBuffer.GetBufferSize();
 980 
 981     TRACE1("DAUDIO_GetBufferSize returns %d\n", bufferSizeInBytes);
 982     return bufferSizeInBytes;
 983 }
 984 
 985 int DAUDIO_StillDraining(void* id, int isSource) {
 986     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 987 
 988     int draining = device->ringBuffer.GetValidByteCount() > 0 ? TRUE : FALSE;
 989 
 990     TRACE1("DAUDIO_StillDraining returns %d\n", draining);
 991     return draining;
 992 }
 993 
 994 int DAUDIO_Flush(void* id, int isSource) {
 995     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
 996     TRACE0("DAUDIO_Flush\n");
 997 
 998     device->ringBuffer.Flush();
 999 
1000     return TRUE;
1001 }
1002 
1003 int DAUDIO_GetAvailable(void* id, int isSource) {
1004     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
1005 
1006     int bytesInBuffer = device->ringBuffer.GetValidByteCount();
1007     if (isSource) {
1008         return device->ringBuffer.GetBufferSize() - bytesInBuffer;
1009     } else {
1010         return bytesInBuffer;
1011     }
1012 }
1013 
1014 INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
1015     OSX_DirectAudioDevice *device = (OSX_DirectAudioDevice*)id;
1016     INT64 position;
1017 
1018     if (isSource) {
1019         position = javaBytePos - device->ringBuffer.GetValidByteCount();
1020     } else {
1021         position = javaBytePos + device->ringBuffer.GetValidByteCount();
1022     }
1023 
1024     TRACE2("DAUDIO_GetBytePosition returns %lld (javaBytePos = %lld)\n", (long long)position, (long long)javaBytePos);
1025     return position;
1026 }
1027 
1028 void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
1029     // no need javaBytePos (it's available in DAUDIO_GetBytePosition)
1030 }
1031 
1032 int DAUDIO_RequiresServicing(void* id, int isSource) {
1033     return FALSE;
1034 }
1035 
1036 void DAUDIO_Service(void* id, int isSource) {
1037     // unreachable
1038 }
1039 
1040 #endif  // USE_DAUDIO == TRUE