168513a70bcd92384395513322f1b801e7bf9c729Steve Block/*
268513a70bcd92384395513322f1b801e7bf9c729Steve Block * Copyright (C) 2010 Google Inc. All rights reserved.
368513a70bcd92384395513322f1b801e7bf9c729Steve Block *
468513a70bcd92384395513322f1b801e7bf9c729Steve Block * Redistribution and use in source and binary forms, with or without
568513a70bcd92384395513322f1b801e7bf9c729Steve Block * modification, are permitted provided that the following conditions
668513a70bcd92384395513322f1b801e7bf9c729Steve Block * are met:
768513a70bcd92384395513322f1b801e7bf9c729Steve Block *
868513a70bcd92384395513322f1b801e7bf9c729Steve Block * 1.  Redistributions of source code must retain the above copyright
968513a70bcd92384395513322f1b801e7bf9c729Steve Block *     notice, this list of conditions and the following disclaimer.
1068513a70bcd92384395513322f1b801e7bf9c729Steve Block * 2.  Redistributions in binary form must reproduce the above copyright
1168513a70bcd92384395513322f1b801e7bf9c729Steve Block *     notice, this list of conditions and the following disclaimer in the
1268513a70bcd92384395513322f1b801e7bf9c729Steve Block *     documentation and/or other materials provided with the distribution.
1368513a70bcd92384395513322f1b801e7bf9c729Steve Block * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
1468513a70bcd92384395513322f1b801e7bf9c729Steve Block *     its contributors may be used to endorse or promote products derived
1568513a70bcd92384395513322f1b801e7bf9c729Steve Block *     from this software without specific prior written permission.
1668513a70bcd92384395513322f1b801e7bf9c729Steve Block *
1768513a70bcd92384395513322f1b801e7bf9c729Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
1868513a70bcd92384395513322f1b801e7bf9c729Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1968513a70bcd92384395513322f1b801e7bf9c729Steve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2068513a70bcd92384395513322f1b801e7bf9c729Steve Block * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
2168513a70bcd92384395513322f1b801e7bf9c729Steve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2268513a70bcd92384395513322f1b801e7bf9c729Steve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2368513a70bcd92384395513322f1b801e7bf9c729Steve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2468513a70bcd92384395513322f1b801e7bf9c729Steve Block * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2568513a70bcd92384395513322f1b801e7bf9c729Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2668513a70bcd92384395513322f1b801e7bf9c729Steve Block * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2768513a70bcd92384395513322f1b801e7bf9c729Steve Block */
2868513a70bcd92384395513322f1b801e7bf9c729Steve Block
2968513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "config.h"
3068513a70bcd92384395513322f1b801e7bf9c729Steve Block
3168513a70bcd92384395513322f1b801e7bf9c729Steve Block#if ENABLE(WEB_AUDIO)
3268513a70bcd92384395513322f1b801e7bf9c729Steve Block
3368513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "AudioFileReaderMac.h"
3468513a70bcd92384395513322f1b801e7bf9c729Steve Block
3568513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "AudioBus.h"
3668513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "AudioFileReader.h"
3768513a70bcd92384395513322f1b801e7bf9c729Steve Block#include <CoreFoundation/CoreFoundation.h>
386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner#include <CoreServices/CoreServices.h>
3968513a70bcd92384395513322f1b801e7bf9c729Steve Block
4068513a70bcd92384395513322f1b801e7bf9c729Steve Blocknamespace WebCore {
4168513a70bcd92384395513322f1b801e7bf9c729Steve Block
4268513a70bcd92384395513322f1b801e7bf9c729Steve Blockstatic AudioBufferList* createAudioBufferList(size_t numberOfBuffers)
4368513a70bcd92384395513322f1b801e7bf9c729Steve Block{
4468513a70bcd92384395513322f1b801e7bf9c729Steve Block    size_t bufferListSize = sizeof(AudioBufferList) - sizeof(AudioBuffer);
4568513a70bcd92384395513322f1b801e7bf9c729Steve Block    bufferListSize += numberOfBuffers * sizeof(AudioBuffer);
4668513a70bcd92384395513322f1b801e7bf9c729Steve Block
4768513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioBufferList* bufferList = static_cast<AudioBufferList*>(calloc(1, bufferListSize));
4868513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (bufferList)
4968513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferList->mNumberBuffers = numberOfBuffers;
5068513a70bcd92384395513322f1b801e7bf9c729Steve Block
5168513a70bcd92384395513322f1b801e7bf9c729Steve Block    return bufferList;
5268513a70bcd92384395513322f1b801e7bf9c729Steve Block}
5368513a70bcd92384395513322f1b801e7bf9c729Steve Block
5468513a70bcd92384395513322f1b801e7bf9c729Steve Blockstatic void destroyAudioBufferList(AudioBufferList* bufferList)
5568513a70bcd92384395513322f1b801e7bf9c729Steve Block{
5668513a70bcd92384395513322f1b801e7bf9c729Steve Block    free(bufferList);
5768513a70bcd92384395513322f1b801e7bf9c729Steve Block}
5868513a70bcd92384395513322f1b801e7bf9c729Steve Block
5968513a70bcd92384395513322f1b801e7bf9c729Steve BlockAudioFileReader::AudioFileReader(const char* filePath)
6068513a70bcd92384395513322f1b801e7bf9c729Steve Block    : m_data(0)
6168513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_dataSize(0)
6268513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_filePath(filePath)
6368513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_audioFileID(0)
6468513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_extAudioFileRef(0)
6568513a70bcd92384395513322f1b801e7bf9c729Steve Block{
6668513a70bcd92384395513322f1b801e7bf9c729Steve Block    FSRef fsref;
6768513a70bcd92384395513322f1b801e7bf9c729Steve Block    OSStatus result = FSPathMakeRef((UInt8*)filePath, &fsref, 0);
6868513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (result != noErr)
6968513a70bcd92384395513322f1b801e7bf9c729Steve Block        return;
7068513a70bcd92384395513322f1b801e7bf9c729Steve Block
7168513a70bcd92384395513322f1b801e7bf9c729Steve Block    CFURLRef urlRef = CFURLCreateFromFSRef(0, &fsref);
7268513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (!urlRef)
7368513a70bcd92384395513322f1b801e7bf9c729Steve Block        return;
7468513a70bcd92384395513322f1b801e7bf9c729Steve Block
7568513a70bcd92384395513322f1b801e7bf9c729Steve Block    ExtAudioFileOpenURL(urlRef, &m_extAudioFileRef);
7668513a70bcd92384395513322f1b801e7bf9c729Steve Block
7768513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (urlRef)
7868513a70bcd92384395513322f1b801e7bf9c729Steve Block        CFRelease(urlRef);
7968513a70bcd92384395513322f1b801e7bf9c729Steve Block}
8068513a70bcd92384395513322f1b801e7bf9c729Steve Block
8168513a70bcd92384395513322f1b801e7bf9c729Steve BlockAudioFileReader::AudioFileReader(const void* data, size_t dataSize)
8268513a70bcd92384395513322f1b801e7bf9c729Steve Block    : m_data(data)
8368513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_dataSize(dataSize)
8468513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_filePath(0)
8568513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_audioFileID(0)
8668513a70bcd92384395513322f1b801e7bf9c729Steve Block    , m_extAudioFileRef(0)
8768513a70bcd92384395513322f1b801e7bf9c729Steve Block{
8868513a70bcd92384395513322f1b801e7bf9c729Steve Block    OSStatus result = AudioFileOpenWithCallbacks(this, readProc, 0, getSizeProc, 0, 0, &m_audioFileID);
8968513a70bcd92384395513322f1b801e7bf9c729Steve Block
9068513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (result != noErr)
9168513a70bcd92384395513322f1b801e7bf9c729Steve Block        return;
9268513a70bcd92384395513322f1b801e7bf9c729Steve Block
9368513a70bcd92384395513322f1b801e7bf9c729Steve Block    result = ExtAudioFileWrapAudioFileID(m_audioFileID, false, &m_extAudioFileRef);
9468513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (result != noErr)
9568513a70bcd92384395513322f1b801e7bf9c729Steve Block        m_extAudioFileRef = 0;
9668513a70bcd92384395513322f1b801e7bf9c729Steve Block}
9768513a70bcd92384395513322f1b801e7bf9c729Steve Block
9868513a70bcd92384395513322f1b801e7bf9c729Steve BlockAudioFileReader::~AudioFileReader()
9968513a70bcd92384395513322f1b801e7bf9c729Steve Block{
10068513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (m_extAudioFileRef)
10168513a70bcd92384395513322f1b801e7bf9c729Steve Block        ExtAudioFileDispose(m_extAudioFileRef);
10268513a70bcd92384395513322f1b801e7bf9c729Steve Block
10368513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_extAudioFileRef = 0;
10468513a70bcd92384395513322f1b801e7bf9c729Steve Block
10568513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (m_audioFileID)
10668513a70bcd92384395513322f1b801e7bf9c729Steve Block        AudioFileClose(m_audioFileID);
10768513a70bcd92384395513322f1b801e7bf9c729Steve Block
10868513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_audioFileID = 0;
10968513a70bcd92384395513322f1b801e7bf9c729Steve Block}
11068513a70bcd92384395513322f1b801e7bf9c729Steve Block
11168513a70bcd92384395513322f1b801e7bf9c729Steve BlockOSStatus AudioFileReader::readProc(void* clientData, SInt64 position, UInt32 requestCount, void* buffer, UInt32* actualCount)
11268513a70bcd92384395513322f1b801e7bf9c729Steve Block{
11368513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioFileReader* audioFileReader = static_cast<AudioFileReader*>(clientData);
11468513a70bcd92384395513322f1b801e7bf9c729Steve Block
11568513a70bcd92384395513322f1b801e7bf9c729Steve Block    size_t dataSize = audioFileReader->dataSize();
11668513a70bcd92384395513322f1b801e7bf9c729Steve Block    const void* data = audioFileReader->data();
11768513a70bcd92384395513322f1b801e7bf9c729Steve Block    size_t bytesToRead = 0;
11868513a70bcd92384395513322f1b801e7bf9c729Steve Block
11968513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (static_cast<UInt64>(position) < dataSize) {
12068513a70bcd92384395513322f1b801e7bf9c729Steve Block        size_t bytesAvailable = dataSize - static_cast<size_t>(position);
12168513a70bcd92384395513322f1b801e7bf9c729Steve Block        bytesToRead = requestCount <= bytesAvailable ? requestCount : bytesAvailable;
12268513a70bcd92384395513322f1b801e7bf9c729Steve Block        memcpy(buffer, static_cast<const char*>(data) + position, bytesToRead);
12368513a70bcd92384395513322f1b801e7bf9c729Steve Block    } else
12468513a70bcd92384395513322f1b801e7bf9c729Steve Block        bytesToRead = 0;
12568513a70bcd92384395513322f1b801e7bf9c729Steve Block
12668513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (actualCount)
12768513a70bcd92384395513322f1b801e7bf9c729Steve Block        *actualCount = bytesToRead;
12868513a70bcd92384395513322f1b801e7bf9c729Steve Block
12968513a70bcd92384395513322f1b801e7bf9c729Steve Block    return noErr;
13068513a70bcd92384395513322f1b801e7bf9c729Steve Block}
13168513a70bcd92384395513322f1b801e7bf9c729Steve Block
13268513a70bcd92384395513322f1b801e7bf9c729Steve BlockSInt64 AudioFileReader::getSizeProc(void* clientData)
13368513a70bcd92384395513322f1b801e7bf9c729Steve Block{
13468513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioFileReader* audioFileReader = static_cast<AudioFileReader*>(clientData);
13568513a70bcd92384395513322f1b801e7bf9c729Steve Block    return audioFileReader->dataSize();
13668513a70bcd92384395513322f1b801e7bf9c729Steve Block}
13768513a70bcd92384395513322f1b801e7bf9c729Steve Block
13868513a70bcd92384395513322f1b801e7bf9c729Steve BlockPassOwnPtr<AudioBus> AudioFileReader::createBus(double sampleRate, bool mixToMono)
13968513a70bcd92384395513322f1b801e7bf9c729Steve Block{
14068513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (!m_extAudioFileRef)
14168513a70bcd92384395513322f1b801e7bf9c729Steve Block        return 0;
14268513a70bcd92384395513322f1b801e7bf9c729Steve Block
14368513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Get file's data format
14468513a70bcd92384395513322f1b801e7bf9c729Steve Block    UInt32 size = sizeof(m_fileDataFormat);
14568513a70bcd92384395513322f1b801e7bf9c729Steve Block    OSStatus result = ExtAudioFileGetProperty(m_extAudioFileRef, kExtAudioFileProperty_FileDataFormat, &size, &m_fileDataFormat);
14668513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (result != noErr)
14768513a70bcd92384395513322f1b801e7bf9c729Steve Block        return 0;
14868513a70bcd92384395513322f1b801e7bf9c729Steve Block
14968513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Number of channels
15068513a70bcd92384395513322f1b801e7bf9c729Steve Block    size_t numberOfChannels = m_fileDataFormat.mChannelsPerFrame;
15168513a70bcd92384395513322f1b801e7bf9c729Steve Block
15268513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Number of frames
15368513a70bcd92384395513322f1b801e7bf9c729Steve Block    SInt64 numberOfFrames64 = 0;
15468513a70bcd92384395513322f1b801e7bf9c729Steve Block    size = sizeof(numberOfFrames64);
15568513a70bcd92384395513322f1b801e7bf9c729Steve Block    result = ExtAudioFileGetProperty(m_extAudioFileRef, kExtAudioFileProperty_FileLengthFrames, &size, &numberOfFrames64);
15668513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (result != noErr)
15768513a70bcd92384395513322f1b801e7bf9c729Steve Block        return 0;
15868513a70bcd92384395513322f1b801e7bf9c729Steve Block
15968513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Sample-rate
16068513a70bcd92384395513322f1b801e7bf9c729Steve Block    double fileSampleRate = m_fileDataFormat.mSampleRate;
16168513a70bcd92384395513322f1b801e7bf9c729Steve Block
16268513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Make client format same number of channels as file format, but tweak a few things.
16368513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Client format will be linear PCM (canonical), and potentially change sample-rate.
16468513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat = m_fileDataFormat;
16568513a70bcd92384395513322f1b801e7bf9c729Steve Block
16668513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mFormatID = kAudioFormatLinearPCM;
16768513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mFormatFlags = kAudioFormatFlagsCanonical;
16868513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mBitsPerChannel = 8 * sizeof(AudioSampleType);
16968513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mChannelsPerFrame = numberOfChannels;
17068513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mFramesPerPacket = 1;
17168513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mBytesPerPacket = sizeof(AudioSampleType);
17268513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mBytesPerFrame = sizeof(AudioSampleType);
17368513a70bcd92384395513322f1b801e7bf9c729Steve Block    m_clientDataFormat.mFormatFlags |= kAudioFormatFlagIsNonInterleaved;
17468513a70bcd92384395513322f1b801e7bf9c729Steve Block
17568513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (sampleRate)
17668513a70bcd92384395513322f1b801e7bf9c729Steve Block        m_clientDataFormat.mSampleRate = sampleRate;
17768513a70bcd92384395513322f1b801e7bf9c729Steve Block
17868513a70bcd92384395513322f1b801e7bf9c729Steve Block    result = ExtAudioFileSetProperty(m_extAudioFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &m_clientDataFormat);
17968513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (result != noErr)
18068513a70bcd92384395513322f1b801e7bf9c729Steve Block        return 0;
18168513a70bcd92384395513322f1b801e7bf9c729Steve Block
18268513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Change numberOfFrames64 to destination sample-rate
18368513a70bcd92384395513322f1b801e7bf9c729Steve Block    numberOfFrames64 = numberOfFrames64 * (m_clientDataFormat.mSampleRate / fileSampleRate);
18468513a70bcd92384395513322f1b801e7bf9c729Steve Block    size_t numberOfFrames = static_cast<size_t>(numberOfFrames64);
18568513a70bcd92384395513322f1b801e7bf9c729Steve Block
18668513a70bcd92384395513322f1b801e7bf9c729Steve Block    size_t busChannelCount = mixToMono ? 1 : numberOfChannels;
18768513a70bcd92384395513322f1b801e7bf9c729Steve Block
18868513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Create AudioBus where we'll put the PCM audio data
18968513a70bcd92384395513322f1b801e7bf9c729Steve Block    OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(busChannelCount, numberOfFrames));
19068513a70bcd92384395513322f1b801e7bf9c729Steve Block    audioBus->setSampleRate(m_clientDataFormat.mSampleRate); // save for later
19168513a70bcd92384395513322f1b801e7bf9c729Steve Block
19268513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Only allocated in the mixToMono case
19368513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioFloatArray bufL;
19468513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioFloatArray bufR;
19568513a70bcd92384395513322f1b801e7bf9c729Steve Block    float* bufferL = 0;
19668513a70bcd92384395513322f1b801e7bf9c729Steve Block    float* bufferR = 0;
19768513a70bcd92384395513322f1b801e7bf9c729Steve Block
19868513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Setup AudioBufferList in preparation for reading
19968513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioBufferList* bufferList = createAudioBufferList(numberOfChannels);
20068513a70bcd92384395513322f1b801e7bf9c729Steve Block
20168513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (mixToMono && numberOfChannels == 2) {
20268513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufL.resize(numberOfFrames);
20368513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufR.resize(numberOfFrames);
20468513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferL = bufL.data();
20568513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferR = bufR.data();
20668513a70bcd92384395513322f1b801e7bf9c729Steve Block
20768513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferList->mBuffers[0].mNumberChannels = 1;
20868513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferList->mBuffers[0].mDataByteSize = numberOfFrames * sizeof(float);
20968513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferList->mBuffers[0].mData = bufferL;
21068513a70bcd92384395513322f1b801e7bf9c729Steve Block
21168513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferList->mBuffers[1].mNumberChannels = 1;
21268513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferList->mBuffers[1].mDataByteSize = numberOfFrames * sizeof(float);
21368513a70bcd92384395513322f1b801e7bf9c729Steve Block        bufferList->mBuffers[1].mData = bufferR;
21468513a70bcd92384395513322f1b801e7bf9c729Steve Block    } else {
21568513a70bcd92384395513322f1b801e7bf9c729Steve Block        ASSERT(!mixToMono || numberOfChannels == 1);
21668513a70bcd92384395513322f1b801e7bf9c729Steve Block
21768513a70bcd92384395513322f1b801e7bf9c729Steve Block        // for True-stereo (numberOfChannels == 4)
21868513a70bcd92384395513322f1b801e7bf9c729Steve Block        for (size_t i = 0; i < numberOfChannels; ++i) {
21968513a70bcd92384395513322f1b801e7bf9c729Steve Block            bufferList->mBuffers[i].mNumberChannels = 1;
22068513a70bcd92384395513322f1b801e7bf9c729Steve Block            bufferList->mBuffers[i].mDataByteSize = numberOfFrames * sizeof(float);
22168513a70bcd92384395513322f1b801e7bf9c729Steve Block            bufferList->mBuffers[i].mData = audioBus->channel(i)->data();
22268513a70bcd92384395513322f1b801e7bf9c729Steve Block        }
22368513a70bcd92384395513322f1b801e7bf9c729Steve Block    }
22468513a70bcd92384395513322f1b801e7bf9c729Steve Block
22568513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Read from the file (or in-memory version)
22668513a70bcd92384395513322f1b801e7bf9c729Steve Block    UInt32 framesToRead = numberOfFrames;
22768513a70bcd92384395513322f1b801e7bf9c729Steve Block    result = ExtAudioFileRead(m_extAudioFileRef, &framesToRead, bufferList);
22868513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (result != noErr)
22968513a70bcd92384395513322f1b801e7bf9c729Steve Block        return 0;
23068513a70bcd92384395513322f1b801e7bf9c729Steve Block
23168513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (mixToMono && numberOfChannels == 2) {
23268513a70bcd92384395513322f1b801e7bf9c729Steve Block        // Mix stereo down to mono
23368513a70bcd92384395513322f1b801e7bf9c729Steve Block        float* destL = audioBus->channel(0)->data();
23468513a70bcd92384395513322f1b801e7bf9c729Steve Block        for (size_t i = 0; i < numberOfFrames; i++)
23568513a70bcd92384395513322f1b801e7bf9c729Steve Block            destL[i] = 0.5f * (bufferL[i] + bufferR[i]);
23668513a70bcd92384395513322f1b801e7bf9c729Steve Block    }
23768513a70bcd92384395513322f1b801e7bf9c729Steve Block
23868513a70bcd92384395513322f1b801e7bf9c729Steve Block    // Cleanup
23968513a70bcd92384395513322f1b801e7bf9c729Steve Block    destroyAudioBufferList(bufferList);
24068513a70bcd92384395513322f1b801e7bf9c729Steve Block
24168513a70bcd92384395513322f1b801e7bf9c729Steve Block    return audioBus.release();
24268513a70bcd92384395513322f1b801e7bf9c729Steve Block}
24368513a70bcd92384395513322f1b801e7bf9c729Steve Block
24468513a70bcd92384395513322f1b801e7bf9c729Steve BlockPassOwnPtr<AudioBus> createBusFromAudioFile(const char* filePath, bool mixToMono, double sampleRate)
24568513a70bcd92384395513322f1b801e7bf9c729Steve Block{
24668513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioFileReader reader(filePath);
24768513a70bcd92384395513322f1b801e7bf9c729Steve Block    return reader.createBus(sampleRate, mixToMono);
24868513a70bcd92384395513322f1b801e7bf9c729Steve Block}
24968513a70bcd92384395513322f1b801e7bf9c729Steve Block
25068513a70bcd92384395513322f1b801e7bf9c729Steve BlockPassOwnPtr<AudioBus> createBusFromInMemoryAudioFile(const void* data, size_t dataSize, bool mixToMono, double sampleRate)
25168513a70bcd92384395513322f1b801e7bf9c729Steve Block{
25268513a70bcd92384395513322f1b801e7bf9c729Steve Block    AudioFileReader reader(data, dataSize);
25368513a70bcd92384395513322f1b801e7bf9c729Steve Block    return reader.createBus(sampleRate, mixToMono);
25468513a70bcd92384395513322f1b801e7bf9c729Steve Block}
25568513a70bcd92384395513322f1b801e7bf9c729Steve Block
25668513a70bcd92384395513322f1b801e7bf9c729Steve Block} // WebCore
25768513a70bcd92384395513322f1b801e7bf9c729Steve Block
25868513a70bcd92384395513322f1b801e7bf9c729Steve Block#endif // ENABLE(WEB_AUDIO)
259