tizen beta release
[framework/web/webkit-efl.git] / Source / WebCore / platform / audio / mac / AudioDestinationMac.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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.
16  *
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.
27  */
28
29 #include "config.h"
30
31 #if ENABLE(WEB_AUDIO)
32
33 #include "AudioDestinationMac.h"
34
35 #include "AudioSourceProvider.h"
36 #include "FloatConversion.h"
37 #include <CoreAudio/AudioHardware.h>
38
39 namespace WebCore {
40
41 const int kBufferSize = 128;
42
43 // Factory method: Mac-implementation
44 PassOwnPtr<AudioDestination> AudioDestination::create(AudioSourceProvider& provider, float sampleRate)
45 {
46     return adoptPtr(new AudioDestinationMac(provider, sampleRate));
47 }
48
49 float AudioDestination::hardwareSampleRate()
50 {
51     // Determine the default output device's sample-rate.
52     AudioDeviceID deviceID = kAudioDeviceUnknown;
53     UInt32 infoSize = sizeof(deviceID);
54
55     AudioObjectPropertyAddress defaultOutputDeviceAddress = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
56     OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultOutputDeviceAddress, 0, 0, &infoSize, (void*)&deviceID);
57     if (result)
58         return 0; // error
59
60     Float64 nominalSampleRate;
61     infoSize = sizeof(Float64);
62
63     AudioObjectPropertyAddress nominalSampleRateAddress = { kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
64     result = AudioObjectGetPropertyData(deviceID, &nominalSampleRateAddress, 0, 0, &infoSize, (void*)&nominalSampleRate);
65     if (result)
66         return 0; // error
67
68     return narrowPrecisionToFloat(nominalSampleRate);
69 }
70
71 AudioDestinationMac::AudioDestinationMac(AudioSourceProvider& provider, float sampleRate)
72     : m_outputUnit(0)
73     , m_provider(provider)
74     , m_renderBus(2, kBufferSize, false)
75     , m_sampleRate(sampleRate)
76     , m_isPlaying(false)
77 {
78     // Open and initialize DefaultOutputUnit
79     AudioComponent comp;
80     AudioComponentDescription desc;
81
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);
88
89     ASSERT(comp);
90
91     OSStatus result = AudioComponentInstanceNew(comp, &m_outputUnit);
92     ASSERT(!result);
93
94     result = AudioUnitInitialize(m_outputUnit);
95     ASSERT(!result);
96
97     configure();
98 }
99
100 AudioDestinationMac::~AudioDestinationMac()
101 {
102     if (m_outputUnit)
103         AudioComponentInstanceDispose(m_outputUnit);
104 }
105
106 void AudioDestinationMac::configure()
107 {
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));
113     ASSERT(!result);
114
115     // Set stream format
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);
125
126     result = AudioUnitSetProperty(m_outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, (void*)&streamFormat, sizeof(AudioStreamBasicDescription));
127     ASSERT(!result);
128
129     // Set the buffer frame size.
130     UInt32 bufferSize = kBufferSize;
131     result = AudioUnitSetProperty(m_outputUnit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Output, 0, (void*)&bufferSize, sizeof(bufferSize));
132     ASSERT(!result);
133 }
134
135 void AudioDestinationMac::start()
136 {
137     OSStatus result = AudioOutputUnitStart(m_outputUnit);
138
139     if (!result)
140         m_isPlaying = true;
141 }
142
143 void AudioDestinationMac::stop()
144 {
145     OSStatus result = AudioOutputUnitStop(m_outputUnit);
146
147     if (!result)
148         m_isPlaying = false;
149 }
150
151 // Pulls on our provider to get rendered audio stream.
152 OSStatus AudioDestinationMac::render(UInt32 numberOfFrames, AudioBufferList* ioData)
153 {
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);
157
158     m_provider.provideInput(&m_renderBus, numberOfFrames);
159
160     return noErr;
161 }
162
163 // DefaultOutputUnit callback
164 OSStatus AudioDestinationMac::inputProc(void* userData, AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32 /*busNumber*/, UInt32 numberOfFrames, AudioBufferList* ioData)
165 {
166     AudioDestinationMac* audioOutput = static_cast<AudioDestinationMac*>(userData);
167     return audioOutput->render(numberOfFrames, ioData);
168 }
169
170 } // namespace WebCore
171
172 #endif // ENABLE(WEB_AUDIO)