diff --git a/src/media/audio/audiolayer.cpp b/src/media/audio/audiolayer.cpp index 11b8e2597fd53b9604a2a715d76711de75fee88a..302ab23bbfad02eb68c45373146658ceab9e4b3d 100644 --- a/src/media/audio/audiolayer.cpp +++ b/src/media/audio/audiolayer.cpp @@ -62,6 +62,7 @@ void AudioLayer::hardwareFormatAvailable(AudioFormat playback) void AudioLayer::hardwareInputFormatAvailable(AudioFormat capture) { + RING_DBG("Hardware input audio format available : %s", capture.toString().c_str()); inputResampler_->setFormat(capture); } diff --git a/src/media/audio/coreaudio/Makefile.am b/src/media/audio/coreaudio/Makefile.am index c30686629cbf82269f0daa3abb35dc47d1effa0f..dd886ec75b83f209c68e46d96a2de64a4b437b3f 100644 --- a/src/media/audio/coreaudio/Makefile.am +++ b/src/media/audio/coreaudio/Makefile.am @@ -2,11 +2,12 @@ include $(top_srcdir)/globals.mk if HAVE_OSX noinst_LTLIBRARIES = libcoreaudiolayer.la +libcoreaudiolayer_la_SOURCES = osx/corelayer.cpp osx/corelayer.h osx/audiodevice.cpp osx/audiodevice.h endif if HAVE_IOS noinst_LTLIBRARIES = libcoreaudiolayer.la +libcoreaudiolayer_la_SOURCES = ios/corelayer.cpp ios/corelayer.h endif -libcoreaudiolayer_la_SOURCES = corelayer.cpp corelayer.h audiodevice.cpp audiodevice.h libcoreaudiolayer_la_CXXFLAGS = -I$(top_srcdir)/src diff --git a/src/media/audio/coreaudio/ios/corelayer.cpp b/src/media/audio/coreaudio/ios/corelayer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d3e9a04a855409158fb5a743845600c8258e392 --- /dev/null +++ b/src/media/audio/coreaudio/ios/corelayer.cpp @@ -0,0 +1,463 @@ +/* + * Copyright (C) 2004-2018 Savoir-faire Linux Inc. + * + * Author: Philippe Groarke <philippe.groarke@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "corelayer.h" +#include "manager.h" +#include "noncopyable.h" +#include "audio/resampler.h" +#include "audio/ringbufferpool.h" +#include "audio/ringbuffer.h" + +#include <cmath> +#include <vector> + +namespace ring { + +// AudioLayer implementation. +CoreLayer::CoreLayer(const AudioPreference &pref) + : AudioLayer(pref) + , indexIn_(pref.getAlsaCardin()) + , indexOut_(pref.getAlsaCardout()) + , indexRing_(pref.getAlsaCardring()) + , playbackBuff_(0, audioFormat_) + , mainRingBuffer_(Manager::instance().getRingBufferPool().getRingBuffer(RingBufferPool::DEFAULT_ID)) +{} + +CoreLayer::~CoreLayer() +{ + stopStream(); +} + +std::vector<std::string> +CoreLayer::getCaptureDeviceList() const +{ + std::vector<std::string> ret; + return ret; +} + +std::vector<std::string> +CoreLayer::getPlaybackDeviceList() const +{ + std::vector<std::string> ret; + // No need to enumerate devices for iOS. + // The notion of input devices can be ignored, and output devices can describe + // input/output pairs. + // Unavailable options like the receiver on iPad can be ignored by the client. + ret.assign({"built_in_spk", "bluetooth", "headphones", "receiver", "dummy"}); + + return ret; +} + +int +CoreLayer::getAudioDeviceIndex(const std::string& name, DeviceType type) const +{ + return 0; +} + +std::string +CoreLayer::getAudioDeviceName(int index, DeviceType type) const +{ + return ""; +} + +void +CoreLayer::initAudioLayerIO() +{ + RING_DBG("iOS CoreLayer - initializing audio session"); + + AudioComponentDescription outputUnitDescription; + outputUnitDescription.componentType = kAudioUnitType_Output; + outputUnitDescription.componentSubType = kAudioUnitSubType_VoiceProcessingIO; + outputUnitDescription.componentManufacturer = kAudioUnitManufacturer_Apple; + outputUnitDescription.componentFlags = 0; + outputUnitDescription.componentFlagsMask = 0; + + auto comp = AudioComponentFindNext(nullptr, &outputUnitDescription); + if (comp == nullptr) { + RING_ERR("Can't find default output audio component."); + return; + } + + checkErr(AudioComponentInstanceNew(comp, &ioUnit_)); + + UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord; + AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, + sizeof(audioCategory), + &audioCategory); + + auto playBackDeviceList = getPlaybackDeviceList(); + RING_DBG("Setting playback device: %s", playBackDeviceList[indexOut_].c_str()); + switch(indexOut_) { + case 0: + UInt32 setSpeaker; + setSpeaker = 1; + checkErr(AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, + sizeof(setSpeaker), + &setSpeaker)); + break; + case 1: + case 2: + break; + case 3: + UInt32 audioRouteOverrideNone; + audioRouteOverrideNone = kAudioSessionOverrideAudioRoute_None; + checkErr(AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, + sizeof(audioRouteOverrideNone), + &audioRouteOverrideNone)); + case 4: + break; + } + + setupOutputBus(); + setupInputBus(); + bindCallbacks(); +} + +void +CoreLayer::setupOutputBus() { + RING_DBG("iOS CoreLayer - initializing output bus"); + + AudioUnitScope outputBus = 0; + UInt32 size; + + AudioStreamBasicDescription outputASBD; + size = sizeof(outputASBD); + + Float64 outSampleRate; + size = sizeof(outSampleRate); + AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, + &size, + &outSampleRate); + outputASBD.mSampleRate = outSampleRate; + outputASBD.mFormatID = kAudioFormatLinearPCM; + outputASBD.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; + + audioFormat_ = {static_cast<unsigned int>(outputASBD.mSampleRate), + static_cast<unsigned int>(outputASBD.mChannelsPerFrame)}; + + size = sizeof(outputASBD); + checkErr(AudioUnitGetProperty(ioUnit_, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + outputBus, + &outputASBD, + &size)); + + // Only change sample rate. + outputASBD.mSampleRate = audioFormat_.sample_rate; + + // Set output steam format + checkErr(AudioUnitSetProperty(ioUnit_, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + outputBus, + &outputASBD, + size)); + + hardwareFormatAvailable(audioFormat_); +} + +void +CoreLayer::setupInputBus() { + RING_DBG("Initializing input bus"); + + AudioUnitScope inputBus = 1; + UInt32 size; + + AudioStreamBasicDescription inputASBD; + size = sizeof(inputASBD); + + // Enable input + UInt32 flag = 1; + checkErr(AudioUnitSetProperty (ioUnit_, + kAudioOutputUnitProperty_EnableIO, + kAudioUnitScope_Input, + inputBus, + &flag, + sizeof(flag))); + + // Setup audio formats + checkErr(AudioUnitGetProperty(ioUnit_, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + inputBus, + &inputASBD, + &size)); + + Float64 inSampleRate; + size = sizeof(Float64); + AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, + &size, + &inSampleRate); + inputASBD.mSampleRate = inSampleRate; + inputASBD.mFormatID = kAudioFormatLinearPCM; + inputASBD.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked; + + audioInputFormat_ = {static_cast<unsigned int>(inputASBD.mSampleRate), + static_cast<unsigned int>(inputASBD.mChannelsPerFrame)}; + hardwareInputFormatAvailable(audioInputFormat_); + + // Keep some values to not ask them every time the read callback is fired up + inSampleRate_ = inputASBD.mSampleRate; + inChannelsPerFrame_ = inputASBD.mChannelsPerFrame; + + // Set format on output *SCOPE* in input *BUS*. + checkErr(AudioUnitGetProperty(ioUnit_, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + inputBus, + &inputASBD, + &size)); + + // Keep everything else and change only sample rate (or else SPLOSION!!!) + inputASBD.mSampleRate = audioInputFormat_.sample_rate; + + size = sizeof(inputASBD); + checkErr(AudioUnitSetProperty(ioUnit_, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + inputBus, + &inputASBD, + size)); + + // Input buffer setup. Note that ioData is empty and we have to store data + // in another buffer. + flag = 0; + AudioUnitSetProperty(ioUnit_, + kAudioUnitProperty_ShouldAllocateBuffer, + kAudioUnitScope_Output, + inputBus, + &flag, + sizeof(flag)); + + Float32 bufferDuration; + size = sizeof(UInt32); + AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, + &size, + &bufferDuration); + UInt32 bufferSizeFrames = audioInputFormat_.sample_rate * bufferDuration; + UInt32 bufferSizeBytes = bufferSizeFrames * sizeof(Float32); + size = offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * inputASBD.mChannelsPerFrame); + rawBuff_.reset(new Byte[size + bufferSizeBytes * inputASBD.mChannelsPerFrame]); + captureBuff_ = reinterpret_cast<::AudioBufferList*>(rawBuff_.get()); + captureBuff_->mNumberBuffers = inputASBD.mChannelsPerFrame; + + auto bufferBasePtr = rawBuff_.get() + size; + for (UInt32 i = 0; i < captureBuff_->mNumberBuffers; ++i) { + captureBuff_->mBuffers[i].mNumberChannels = 1; + captureBuff_->mBuffers[i].mDataByteSize = bufferSizeBytes; + captureBuff_->mBuffers[i].mData = bufferBasePtr + bufferSizeBytes * i; + } +} + +void +CoreLayer::bindCallbacks() { + AURenderCallbackStruct callback; + AudioUnitScope outputBus = 0; + AudioUnitScope inputBus = 1; + + // Output callback setup + callback.inputProc = outputCallback; + callback.inputProcRefCon = this; + + checkErr(AudioUnitSetProperty(ioUnit_, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Global, + outputBus, + &callback, + sizeof(AURenderCallbackStruct))); + + // Input callback setup + callback.inputProc = inputCallback; + callback.inputProcRefCon = this; + + checkErr(AudioUnitSetProperty(ioUnit_, + kAudioOutputUnitProperty_SetInputCallback, + kAudioUnitScope_Global, + inputBus, + &callback, + sizeof(AURenderCallbackStruct))); +} + +void +CoreLayer::startStream() +{ + RING_DBG("iOS CoreLayer - Start Stream"); + + { + std::lock_guard<std::mutex> lock(mutex_); + if (status_ != Status::Idle) + return; + status_ = Status::Started; + } + + dcblocker_.reset(); + + initAudioLayerIO(); + + // Run + checkErr(AudioUnitInitialize(ioUnit_)); + checkErr(AudioOutputUnitStart(ioUnit_)); +} + +void +CoreLayer::destroyAudioLayer() +{ + AudioOutputUnitStop(ioUnit_); + AudioUnitUninitialize(ioUnit_); + AudioComponentInstanceDispose(ioUnit_); +} + +void +CoreLayer::stopStream() +{ + RING_DBG("iOS CoreLayer - Stop Stream"); + + { + std::lock_guard<std::mutex> lock(mutex_); + if (status_ != Status::Started) + return; + status_ = Status::Idle; + } + + destroyAudioLayer(); + + /* Flush the ring buffers */ + flushUrgent(); + flushMain(); +} + +OSStatus +CoreLayer::outputCallback(void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) +{ + static_cast<CoreLayer*>(inRefCon)->write(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); + return kAudioServicesNoError; +} + +void +CoreLayer::write(AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) +{ + auto& ringBuff = getToRing(audioFormat_, inNumberFrames); + auto& playBuff = getToPlay(audioFormat_, inNumberFrames); + + auto& toPlay = ringBuff.frames() > 0 ? ringBuff : playBuff; + + if (toPlay.frames() == 0) { + for (unsigned i = 0; i < audioFormat_.nb_channels; ++i) { + std::fill_n(reinterpret_cast<Float32*>(ioData->mBuffers[i].mData), + ioData->mBuffers[i].mDataByteSize / sizeof(Float32), 0); + } + } else { + for (unsigned i = 0; i < audioFormat_.nb_channels; ++i) { + toPlay.channelToFloat(reinterpret_cast<Float32*>(ioData->mBuffers[i].mData), i); + } + } +} + +OSStatus +CoreLayer::inputCallback(void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) +{ + static_cast<CoreLayer*>(inRefCon)->read(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData); + return kAudioServicesNoError; +} + +void +CoreLayer::read(AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData) +{ + if (inNumberFrames <= 0) { + RING_WARN("No frames for input."); + return; + } + + // Write the mic samples in our buffer + checkErr(AudioUnitRender(ioUnit_, + ioActionFlags, + inTimeStamp, + inBusNumber, + inNumberFrames, + captureBuff_)); + + // Add them to Ring ringbuffer. + const AudioFormat mainBufferFormat = Manager::instance().getRingBufferPool().getInternalAudioFormat(); + bool resample = inSampleRate_ != mainBufferFormat.sample_rate; + + // FIXME: Performance! There *must* be a better way. This is testing only. + auto inBuff = AudioBuffer {inNumberFrames, audioInputFormat_}; + + for (unsigned i = 0; i < inChannelsPerFrame_; ++i) { + auto data = reinterpret_cast<Float32*>(captureBuff_->mBuffers[i].mData); + for (unsigned j = 0; j < inNumberFrames; ++j) { + (*inBuff.getChannel(i))[j] = static_cast<AudioSample>(data[j] * 32768); + } + } + + if (resample) { + //FIXME: May be a multiplication, check alsa vs pulse implementation. + UInt32 outSamples = inNumberFrames * (mainBufferFormat.sample_rate / static_cast<double>(audioInputFormat_.sample_rate)); + auto out = AudioBuffer {outSamples, mainBufferFormat}; + inputResampler_->resample(inBuff, out); + dcblocker_.process(out); + mainRingBuffer_->put(out); + } else { + dcblocker_.process(inBuff); + mainRingBuffer_->put(inBuff); + } +} + +void CoreLayer::updatePreference(AudioPreference &preference, int index, DeviceType type) +{ + switch (type) { + case DeviceType::PLAYBACK: + preference.setAlsaCardout(index); + break; + + case DeviceType::CAPTURE: + preference.setAlsaCardin(index); + break; + + case DeviceType::RINGTONE: + preference.setAlsaCardring(index); + break; + + default: + break; + } +} + +} // namespace ring diff --git a/src/media/audio/coreaudio/ios/corelayer.h b/src/media/audio/coreaudio/ios/corelayer.h new file mode 100644 index 0000000000000000000000000000000000000000..f3d80a2a30ec2287f528b8e25e50f8c85cd13c87 --- /dev/null +++ b/src/media/audio/coreaudio/ios/corelayer.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2004-2018 Savoir-faire Linux Inc. + * + * Author: Philippe Groarke <philippe.groarke@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef CORE_LAYER_H_ +#define CORE_LAYER_H_ + +#include "audio/audiolayer.h" +#include "noncopyable.h" +#include <CoreFoundation/CoreFoundation.h> +#include <AudioToolbox/AudioToolbox.h> + +#define checkErr( err) \ + if(err) { \ + RING_ERR("CoreAudio Error: %ld", static_cast<long>(err)); \ + } + +/** + * @file CoreLayer.h + * @brief Main iOS sound class. Manages the data transfers between the application and the hardware. + */ + +namespace ring { + +class RingBuffer; + +class CoreLayer : public AudioLayer { + public: + CoreLayer(const AudioPreference &pref); + ~CoreLayer(); + + /** + * Scan the sound card available on the system + * @return std::vector<std::string> The vector containing the string description of the card + */ + virtual std::vector<std::string> getCaptureDeviceList() const; + virtual std::vector<std::string> getPlaybackDeviceList() const; + + virtual int getAudioDeviceIndex(const std::string& name, DeviceType type) const; + virtual std::string getAudioDeviceName(int index, DeviceType type) const; + + /** + * Get the index of the audio card for capture + * @return int The index of the card used for capture + */ + virtual int getIndexCapture() const { + return indexIn_; + } + + /** + * Get the index of the audio card for playback + * @return int The index of the card used for playback + */ + virtual int getIndexPlayback() const { + return indexOut_; + } + + /** + * Get the index of the audio card for ringtone (could be differnet from playback) + * @return int The index of the card used for ringtone + */ + virtual int getIndexRingtone() const { + return indexRing_; + } + + /** + * Configure the AudioUnit + */ + void initAudioLayerIO(); + void setupOutputBus(); + void setupInputBus(); + void bindCallbacks(); + + int initAudioStreams(AudioUnit *audioUnit); + + /** + * Start the capture stream and prepare the playback stream. + * The playback starts accordingly to its threshold + * CoreAudio Library API + */ + + virtual void startStream(); + + void destroyAudioLayer(); + + /** + * Stop the playback and capture streams. + * Drops the pending frames and put the capture and playback handles to PREPARED state + * CoreAudio Library API + */ + virtual void stopStream(); + + private: + NON_COPYABLE(CoreLayer); + + void initAudioFormat(); + + static OSStatus outputCallback(void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData); + + void write(AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData); + + static OSStatus inputCallback(void* inRefCon, + AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData); + + void read(AudioUnitRenderActionFlags* ioActionFlags, + const AudioTimeStamp* inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList* ioData); + + virtual void updatePreference(AudioPreference &pref, int index, DeviceType type); + + /** + * Number of audio cards on which capture stream has been opened + */ + int indexIn_; + + /** + * Number of audio cards on which playback stream has been opened + */ + int indexOut_; + + /** + * Number of audio cards on which ringtone stream has been opened + */ + int indexRing_; + + /** Non-interleaved audio buffers */ + AudioBuffer playbackBuff_; + ::AudioBufferList* captureBuff_ {nullptr}; // CoreAudio buffer (pointer is casted rawBuff_) + std::unique_ptr<Byte[]> rawBuff_; // raw allocation of captureBuff_ + + /** Interleaved buffer */ + std::vector<AudioSample> playbackIBuff_; + std::vector<AudioSample> captureIBuff_; + + AudioUnit ioUnit_; + + Float64 inSampleRate_; + UInt32 inChannelsPerFrame_; + + std::shared_ptr<RingBuffer> mainRingBuffer_; +}; + +} // namespace ring + +#endif // CORE_LAYER_H_ diff --git a/src/media/audio/coreaudio/audiodevice.cpp b/src/media/audio/coreaudio/osx/audiodevice.cpp similarity index 100% rename from src/media/audio/coreaudio/audiodevice.cpp rename to src/media/audio/coreaudio/osx/audiodevice.cpp diff --git a/src/media/audio/coreaudio/audiodevice.h b/src/media/audio/coreaudio/osx/audiodevice.h similarity index 100% rename from src/media/audio/coreaudio/audiodevice.h rename to src/media/audio/coreaudio/osx/audiodevice.h diff --git a/src/media/audio/coreaudio/corelayer.cpp b/src/media/audio/coreaudio/osx/corelayer.cpp similarity index 96% rename from src/media/audio/coreaudio/corelayer.cpp rename to src/media/audio/coreaudio/osx/corelayer.cpp index d24bdd436df171f96dd8c0f7a6217edd609923f1..33e47b05b8669cc6f3970c02feb7dabc0fc7ffc5 100644 --- a/src/media/audio/coreaudio/corelayer.cpp +++ b/src/media/audio/coreaudio/osx/corelayer.cpp @@ -49,10 +49,8 @@ CoreLayer::getCaptureDeviceList() const { std::vector<std::string> ret; -#if !TARGET_OS_IPHONE for (const auto& x : getDeviceList(true)) ret.push_back(x.name_); -#endif return ret; } @@ -62,10 +60,8 @@ CoreLayer::getPlaybackDeviceList() const { std::vector<std::string> ret; -#if !TARGET_OS_IPHONE for (const auto& x : getDeviceList(false)) ret.push_back(x.name_); -#endif return ret; } @@ -179,7 +175,6 @@ CoreLayer::initAudioLayerIO() // Input buffer setup. Note that ioData is empty and we have to store data // in another buffer. -#if !TARGET_OS_IPHONE UInt32 bufferSizeFrames = 0; size = sizeof(UInt32); checkErr(AudioUnitGetProperty(ioUnit_, @@ -188,14 +183,6 @@ CoreLayer::initAudioLayerIO() outputBus, &bufferSizeFrames, &size)); -#else - Float32 bufferDuration; - UInt32 propSize = sizeof(Float32); - AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, - &propSize, - &bufferDuration); - UInt32 bufferSizeFrames = audioInputFormat_.sample_rate * bufferDuration; -#endif UInt32 bufferSizeBytes = bufferSizeFrames * sizeof(Float32); size = offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * info.mChannelsPerFrame); @@ -406,7 +393,6 @@ std::vector<AudioDevice> CoreLayer::getDeviceList(bool getCapture) const { std::vector<AudioDevice> ret; -#if !TARGET_OS_IPHONE UInt32 propsize; AudioObjectPropertyAddress theAddress = { @@ -437,7 +423,6 @@ CoreLayer::getDeviceList(bool getCapture) const ret.push_back(std::move(dev)); } } -#endif return ret; } diff --git a/src/media/audio/coreaudio/corelayer.h b/src/media/audio/coreaudio/osx/corelayer.h similarity index 99% rename from src/media/audio/coreaudio/corelayer.h rename to src/media/audio/coreaudio/osx/corelayer.h index 5c22897b5a22663ec49704f2dc0e60abd4a0e64c..48dfbc400ca2979d59648e1f0e9e508b38b43ec5 100644 --- a/src/media/audio/coreaudio/corelayer.h +++ b/src/media/audio/coreaudio/osx/corelayer.h @@ -25,9 +25,7 @@ #include "noncopyable.h" #include <CoreFoundation/CoreFoundation.h> #include <AudioToolbox/AudioToolbox.h> -#if !TARGET_OS_IPHONE #include <CoreAudio/AudioHardware.h> -#endif #define checkErr( err) \ if(err) {\ diff --git a/src/preferences.cpp b/src/preferences.cpp index 608189b8a198ee066f9edec53c8c7150344061e6..3d1b28a898bb3ff9fdbc2bbd2a72562d671cbae6 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -38,8 +38,15 @@ #include "audio/pulseaudio/pulselayer.h" #endif #if HAVE_COREAUDIO -#include "audio/coreaudio/corelayer.h" +#ifdef __APPLE__ +#include <TargetConditionals.h> #endif +#if TARGET_OS_IOS +#include "audio/coreaudio/ios/corelayer.h" +#else +#include "audio/coreaudio/osx/corelayer.h" +#endif /* TARGET_OS_IOS */ +#endif /* HAVE_COREAUDIO */ #if HAVE_PORTAUDIO #include "audio/portaudio/portaudiolayer.h" #endif