SndFile.c revision 27f8dfaea17ab7831a1bd34a02f85d55bacf67b7
1b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten/*
2b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Copyright (C) 2010 The Android Open Source Project
3b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *
4b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * you may not use this file except in compliance with the License.
6b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * You may obtain a copy of the License at
7b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *
8b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *
10b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * See the License for the specific language governing permissions and
14b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten * limitations under the License.
15b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten */
16b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
17b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten/* libsndfile integration */
18b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
19b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#include "sles_allinclusive.h"
20b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
21b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#ifdef USE_SNDFILE
22b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
23b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten// FIXME should run this asynchronously esp. for socket fd, not on mix thread
24b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenvoid SLAPIENTRY SndFile_Callback(SLBufferQueueItf caller, void *pContext)
25b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
26b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    struct SndFile *this = (struct SndFile *) pContext;
27b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    SLresult result;
28b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    if (NULL != this->mRetryBuffer && 0 < this->mRetrySize) {
2927f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        result = (*caller)->Enqueue(caller, this->mRetryBuffer, this->mRetrySize);
30b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result)
31b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            return;     // what, again?
32b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
33b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        this->mRetryBuffer = NULL;
34b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        this->mRetrySize = 0;
35b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return;
36b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
37b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    short *pBuffer = this->mIs0 ? this->mBuffer0 : this->mBuffer1;
38b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    this->mIs0 ^= SL_BOOLEAN_TRUE;
39b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    sf_count_t count;
40b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    // FIXME magic number
41b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    count = sf_read_short(this->mSNDFILE, pBuffer, (sf_count_t) 512);
42b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    if (0 < count) {
43b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        SLuint32 size = count * sizeof(short);
44b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        // FIXME if we had an internal API, could call this directly
45b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        result = (*caller)->Enqueue(caller, pBuffer, size);
46b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        if (SL_RESULT_BUFFER_INSUFFICIENT == result) {
47b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            this->mRetryBuffer = pBuffer;
48b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            this->mRetrySize = size;
49b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten            return;
50b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        }
51b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        assert(SL_RESULT_SUCCESS == result);
52b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
53b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
54b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
55b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLboolean SndFile_IsSupported(const SF_INFO *sfinfo)
56b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{
57b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->format & SF_FORMAT_TYPEMASK) {
58b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case SF_FORMAT_WAV:
59b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
60b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
61b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
62b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
63b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->format & SF_FORMAT_SUBMASK) {
64b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case SF_FORMAT_PCM_16:
65b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
66b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
67b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
68b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
69b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->samplerate) {
70b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case 44100:
71b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
72b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
73b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
74b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
75b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    switch (sfinfo->channels) {
76b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    case 2:
77b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        break;
78b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    default:
79b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten        return SL_BOOLEAN_FALSE;
80b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    }
81b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten    return SL_BOOLEAN_TRUE;
82b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten}
83b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten
84acd88797a1d3b8225bab888d29036e245f275be5Glenn KastenSLresult SndFile_checkAudioPlayerSourceSink(CAudioPlayer *this)
85daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{
86acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    const SLDataSource *pAudioSrc = &this->mDataSource.u.mSource;
87acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    //const SLDataSink *pAudioSnk = &this->mDataSink.u.mSink;
88daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator;
89daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    SLuint32 formatType = *(SLuint32 *)pAudioSrc->pFormat;
90daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    switch (locatorType) {
91daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_BUFFERQUEUE:
92acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten        this->mBufferQueue.mNumBuffers =
93acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten            ((SLDataLocator_BufferQueue *) pAudioSrc->pLocator)->numBuffers;
94daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
95daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    case SL_DATALOCATOR_URI:
96daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        {
97daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator;
98daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        SLchar *uri = dl_uri->URI;
99daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        if (NULL == uri)
100daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
10127f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        // FIXME check other schemes and handle, or return SL_RESULT_CONTENT_UNSUPPORTED
10227f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        if (!strncmp((const char *) uri, "file:///", 8))
10327f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten            uri += 8;
104daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        switch (formatType) {
105daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        case SL_DATAFORMAT_MIME:
106daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            break;
107daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        default:
108daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten            return SL_RESULT_CONTENT_UNSUPPORTED;
109daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
11027f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten        this->mSndFile.mPathname = uri;
111daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        // FIXME magic number, should be configurable
112acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten        this->mBufferQueue.mNumBuffers = 2;
113daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        }
114daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        break;
115daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    default:
116daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten        return SL_RESULT_CONTENT_UNSUPPORTED;
117daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    }
118acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mIs0 = SL_BOOLEAN_TRUE;
119acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mSNDFILE = NULL;
120acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mRetryBuffer = NULL;
121acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten    this->mSndFile.mRetrySize = 0;
122daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten    return SL_RESULT_SUCCESS;
123daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten}
124daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten
125b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif // USE_SNDFILE
126