2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "AudioDestinationMac.h"
35 #include "AudioSourceProvider.h"
36 #include "FloatConversion.h"
37 #include <CoreAudio/AudioHardware.h>
41 const int kBufferSize = 128;
43 // Factory method: Mac-implementation
44 PassOwnPtr<AudioDestination> AudioDestination::create(AudioSourceProvider& provider, float sampleRate)
46 return adoptPtr(new AudioDestinationMac(provider, sampleRate));
49 float AudioDestination::hardwareSampleRate()
51 // Determine the default output device's sample-rate.
52 AudioDeviceID deviceID = kAudioDeviceUnknown;
53 UInt32 infoSize = sizeof(deviceID);
55 AudioObjectPropertyAddress defaultOutputDeviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
56 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultOutputDeviceAddress, 0, 0, &infoSize, (void*)&deviceID);
60 Float64 nominalSampleRate;
61 infoSize = sizeof(Float64);
63 AudioObjectPropertyAddress nominalSampleRateAddress = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
64 result = AudioObjectGetPropertyData(deviceID, &nominalSampleRateAddress, 0, 0, &infoSize, (void*)&nominalSampleRate);
68 return narrowPrecisionToFloat(nominalSampleRate);
71 AudioDestinationMac::AudioDestinationMac(AudioSourceProvider& provider, float sampleRate)
73 , m_provider(provider)
74 , m_renderBus(2, kBufferSize, false)
75 , m_sampleRate(sampleRate)
78 // Open and initialize DefaultOutputUnit
80 AudioComponentDescription desc;
82 desc.componentType = kAudioUnitType_Output;
83 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
84 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
85 desc.componentFlags = 0;
86 desc.componentFlagsMask = 0;
87 comp = AudioComponentFindNext(0, &desc);
91 OSStatus result = AudioComponentInstanceNew(comp, &m_outputUnit);
94 result = AudioUnitInitialize(m_outputUnit);
100 AudioDestinationMac::~AudioDestinationMac()
103 AudioComponentInstanceDispose(m_outputUnit);
106 void AudioDestinationMac::configure()
108 // Set render callback
109 AURenderCallbackStruct input;
110 input.inputProc = inputProc;
111 input.inputProcRefCon = this;
112 OSStatus result = AudioUnitSetProperty(m_outputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &input, sizeof(input));
116 AudioStreamBasicDescription streamFormat;
117 streamFormat.mSampleRate = m_sampleRate;
118 streamFormat.mFormatID = kAudioFormatLinearPCM;
119 streamFormat.mFormatFlags = kAudioFormatFlagsCanonical | kAudioFormatFlagIsNonInterleaved;
120 streamFormat.mBitsPerChannel = 8 * sizeof(AudioSampleType);
121 streamFormat.mChannelsPerFrame = 2;
122 streamFormat.mFramesPerPacket = 1;
123 streamFormat.mBytesPerPacket = sizeof(AudioSampleType);
124 streamFormat.mBytesPerFrame = sizeof(AudioSampleType);
126 result = AudioUnitSetProperty(m_outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, (void*)&streamFormat, sizeof(AudioStreamBasicDescription));
129 // Set the buffer frame size.
130 UInt32 bufferSize = kBufferSize;
131 result = AudioUnitSetProperty(m_outputUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Output, 0, (void*)&bufferSize, sizeof(bufferSize));
135 void AudioDestinationMac::start()
137 OSStatus result = AudioOutputUnitStart(m_outputUnit);
143 void AudioDestinationMac::stop()
145 OSStatus result = AudioOutputUnitStop(m_outputUnit);
151 // Pulls on our provider to get rendered audio stream.
152 OSStatus AudioDestinationMac::render(UInt32 numberOfFrames, AudioBufferList* ioData)
154 AudioBuffer* buffers = ioData->mBuffers;
155 m_renderBus.setChannelMemory(0, (float*)buffers[0].mData, numberOfFrames);
156 m_renderBus.setChannelMemory(1, (float*)buffers[1].mData, numberOfFrames);
158 m_provider.provideInput(&m_renderBus, numberOfFrames);
163 // DefaultOutputUnit callback
164 OSStatus AudioDestinationMac::inputProc(void* userData, AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32 /*busNumber*/, UInt32 numberOfFrames, AudioBufferList* ioData)
166 AudioDestinationMac* audioOutput = static_cast<AudioDestinationMac*>(userData);
167 return audioOutput->render(numberOfFrames, ioData);
170 } // namespace WebCore
172 #endif // ENABLE(WEB_AUDIO)