Allow audio devices with up to 64 channels on Mac.

Does not increase memory requirements. Adds an additional check to ensure
configurations requiring more memory per IO block than the input ring buffer
contains are rejected.

BUG=1904
TESTED=Using Soundflower (64 channels) at 48 kHz as input gives good quality.
Selecting a higher sample rate (96 kHz), which would otherwise give choppy
audio, instead results in an error.

R=henrika@webrtc.org, xians@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/1628004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4198 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
andrew@webrtc.org 2013-06-07 17:56:50 +00:00
parent 1064cf06b0
commit 6f69eb78dd
2 changed files with 66 additions and 56 deletions

View File

@ -374,9 +374,9 @@ int32_t AudioDeviceMac::Init()
}
// Setting RunLoop to NULL here instructs HAL to manage its own thread for
// notifications. This was the default behaviour on OS X 10.5 and earlier, but now
// must be explicitly specified. HAL would otherwise try to use the main thread to
// issue notifications.
// notifications. This was the default behaviour on OS X 10.5 and earlier,
// but now must be explicitly specified. HAL would otherwise try to use the
// main thread to issue notifications.
AudioObjectPropertyAddress propertyAddress = {
kAudioHardwarePropertyRunLoop,
kAudioObjectPropertyScopeGlobal,
@ -495,8 +495,8 @@ int32_t AudioDeviceMac::SpeakerIsAvailable(bool& available)
return 0;
}
// Given that InitSpeaker was successful, we know that a valid speaker exists
//
// Given that InitSpeaker was successful, we know that a valid speaker
// exists.
available = true;
// Close the initialized output mixer
@ -554,8 +554,8 @@ int32_t AudioDeviceMac::MicrophoneIsAvailable(bool& available)
return 0;
}
// Given that InitMicrophone was successful, we know that a valid microphone exists
//
// Given that InitMicrophone was successful, we know that a valid microphone
// exists.
available = true;
// Close the initialized input mixer
@ -1387,7 +1387,7 @@ int32_t AudioDeviceMac::InitPlayout()
if (_outStreamFormat.mChannelsPerFrame > N_DEVICE_CHANNELS)
{
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
"Too many channels on device -> mChannelsPerFrame = %d",
"Too many channels on output device (mChannelsPerFrame = %d)",
_outStreamFormat.mChannelsPerFrame);
return -1;
}
@ -1415,9 +1415,8 @@ int32_t AudioDeviceMac::InitPlayout()
_outStreamFormat.mBytesPerFrame,
_outStreamFormat.mBitsPerChannel);
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
"mFormatFlags = %u, mChannelsPerFrame = %u",
_outStreamFormat.mFormatFlags,
_outStreamFormat.mChannelsPerFrame);
"mFormatFlags = %u",
_outStreamFormat.mFormatFlags);
logCAMsg(kTraceInfo, kTraceAudioDevice, _id, "mFormatID",
(const char *) &_outStreamFormat.mFormatID);
@ -1615,11 +1614,21 @@ int32_t AudioDeviceMac::InitRecording()
if (_inStreamFormat.mChannelsPerFrame > N_DEVICE_CHANNELS)
{
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
", Too many channels on device (mChannelsPerFrame = %d)",
"Too many channels on input device (mChannelsPerFrame = %d)",
_inStreamFormat.mChannelsPerFrame);
return -1;
}
const int io_block_size_samples = _inStreamFormat.mChannelsPerFrame *
_inStreamFormat.mSampleRate / 100 * N_BLOCKS_IO;
if (io_block_size_samples > _captureBufSizeSamples)
{
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
"Input IO block size (%d) is larger than ring buffer (%u)",
io_block_size_samples, _captureBufSizeSamples);
return -1;
}
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
" Input stream format:");
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
@ -1634,9 +1643,8 @@ int32_t AudioDeviceMac::InitRecording()
_inStreamFormat.mBytesPerFrame,
_inStreamFormat.mBitsPerChannel);
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
" mFormatFlags = %u, mChannelsPerFrame = %u",
_inStreamFormat.mFormatFlags,
_inStreamFormat.mChannelsPerFrame);
" mFormatFlags = %u",
_inStreamFormat.mFormatFlags);
logCAMsg(kTraceInfo, kTraceAudioDevice, _id, "mFormatID",
(const char *) &_inStreamFormat.mFormatID);
@ -2629,13 +2637,24 @@ int32_t AudioDeviceMac::HandleStreamFormatChange(
"mBytesPerFrame = %u, mBitsPerChannel = %u",
streamFormat.mBytesPerFrame, streamFormat.mBitsPerChannel);
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
"mFormatFlags = %u, mChannelsPerFrame = %u",
streamFormat.mFormatFlags, streamFormat.mChannelsPerFrame);
"mFormatFlags = %u",
streamFormat.mFormatFlags);
logCAMsg(kTraceInfo, kTraceAudioDevice, _id, "mFormatID",
(const char *) &streamFormat.mFormatID);
if (propertyAddress.mScope == kAudioDevicePropertyScopeInput)
{
const int io_block_size_samples = streamFormat.mChannelsPerFrame *
streamFormat.mSampleRate / 100 * N_BLOCKS_IO;
if (io_block_size_samples > _captureBufSizeSamples)
{
WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
"Input IO block size (%d) is larger than ring buffer (%u)",
io_block_size_samples, _captureBufSizeSamples);
return -1;
}
memcpy(&_inStreamFormat, &streamFormat, sizeof(streamFormat));
if (_inStreamFormat.mChannelsPerFrame >= 2 && (_recChannels == 2))

View File

@ -26,35 +26,26 @@ namespace webrtc
class EventWrapper;
class ThreadWrapper;
const uint32_t N_REC_SAMPLES_PER_SEC = 48000;
const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000;
const int N_REC_SAMPLES_PER_SEC = 48000;
const int N_PLAY_SAMPLES_PER_SEC = 48000;
const uint32_t N_REC_CHANNELS = 1; // default is mono recording
const uint32_t N_PLAY_CHANNELS = 2; // default is stereo playout
const uint32_t N_DEVICE_CHANNELS = 8;
const int N_REC_CHANNELS = 1; // default is mono recording
const int N_PLAY_CHANNELS = 2; // default is stereo playout
const int N_DEVICE_CHANNELS = 64;
const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES = (N_REC_SAMPLES_PER_SEC / 100);
const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES = (N_PLAY_SAMPLES_PER_SEC / 100);
const int ENGINE_REC_BUF_SIZE_IN_SAMPLES = (N_REC_SAMPLES_PER_SEC / 100);
const int ENGINE_PLAY_BUF_SIZE_IN_SAMPLES = (N_PLAY_SAMPLES_PER_SEC / 100);
enum
{
N_BLOCKS_IO = 2
};
enum
{
N_BUFFERS_IN = 10
};
enum
{
N_BUFFERS_OUT = 3
}; // Must be at least N_BLOCKS_IO
const int N_BLOCKS_IO = 2;
const int N_BUFFERS_IN = 2; // Must be at least N_BLOCKS_IO.
const int N_BUFFERS_OUT = 3; // Must be at least N_BLOCKS_IO.
const uint32_t TIMER_PERIOD_MS = (2 * 10 * N_BLOCKS_IO * 1000000);
const int TIMER_PERIOD_MS = (2 * 10 * N_BLOCKS_IO * 1000000);
const uint32_t REC_BUF_SIZE_IN_SAMPLES = (ENGINE_REC_BUF_SIZE_IN_SAMPLES
* N_DEVICE_CHANNELS * N_BUFFERS_IN);
const uint32_t PLAY_BUF_SIZE_IN_SAMPLES =
(ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT);
const int REC_BUF_SIZE_IN_SAMPLES =
ENGINE_REC_BUF_SIZE_IN_SAMPLES * N_DEVICE_CHANNELS * N_BUFFERS_IN;
const int PLAY_BUF_SIZE_IN_SAMPLES =
ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT;
class AudioDeviceMac: public AudioDeviceGeneric
{
@ -384,8 +375,8 @@ private:
semaphore_t _renderSemaphore;
semaphore_t _captureSemaphore;
uint32_t _captureBufSizeSamples;
uint32_t _renderBufSizeSamples;
int _captureBufSizeSamples;
int _renderBufSizeSamples;
};
} // namespace webrtc