SndFile.c revision e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037
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 236a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kastenvoid SndFile_Callback(SLBufferQueueItf caller, void *pContext) 24b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{ 25276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten CAudioPlayer *thisAP = (CAudioPlayer *) pContext; 26e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten object_lock_peek(&thisAP->mObject); 27e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten SLuint32 state = thisAP->mPlay.mState; 28e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten object_unlock_peek(&thisAP->mObject); 29e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten if (SL_PLAYSTATE_PLAYING != state) 30276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten return; 31276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten struct SndFile *this = &thisAP->mSndFile; 32b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten SLresult result; 33b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (NULL != this->mRetryBuffer && 0 < this->mRetrySize) { 3427f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten result = (*caller)->Enqueue(caller, this->mRetryBuffer, this->mRetrySize); 35b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (SL_RESULT_BUFFER_INSUFFICIENT == result) 36b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return; // what, again? 37b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten assert(SL_RESULT_SUCCESS == result); 38b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten this->mRetryBuffer = NULL; 39b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten this->mRetrySize = 0; 40b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return; 41b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 42e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten pthread_mutex_lock(&this->mMutex); 43e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten if (this->mEOF) { 44e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten pthread_mutex_unlock(&this->mMutex); 45e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten return; 46e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 476a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten short *pBuffer = &this->mBuffer[this->mWhich * SndFile_BUFSIZE]; 486a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten if (++this->mWhich >= SndFile_NUMBUFS) 496a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten this->mWhich = 0; 50b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten sf_count_t count; 516a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten count = sf_read_short(this->mSNDFILE, pBuffer, (sf_count_t) SndFile_BUFSIZE); 52e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten if (0 >= count) 53e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten this->mEOF = SL_BOOLEAN_TRUE; 54e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten pthread_mutex_unlock(&this->mMutex); 55b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (0 < count) { 567324a5ab12cc734e2feb4cef8baeda26566d3c92Glenn Kasten SLuint32 size = (SLuint32) (count * sizeof(short)); 57b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten result = (*caller)->Enqueue(caller, pBuffer, size); 58b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (SL_RESULT_BUFFER_INSUFFICIENT == result) { 59b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten this->mRetryBuffer = pBuffer; 60b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten this->mRetrySize = size; 61b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return; 62b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 63b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten assert(SL_RESULT_SUCCESS == result); 64276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten } else { 65e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten object_lock_exclusive(&thisAP->mObject); 66e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten // FIXME Uh not yet - we just ran out of new data to enqueue, 67e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten // but there may still be (partially) full buffers in the queue. 68276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten thisAP->mPlay.mState = SL_PLAYSTATE_PAUSED; 69e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten thisAP->mPlay.mPosition = thisAP->mPlay.mDuration; 70e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten object_unlock_exclusive_attributes(&thisAP->mObject, ATTR_TRANSPORT); 71b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 72b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten} 73b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 74b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLboolean SndFile_IsSupported(const SF_INFO *sfinfo) 75b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{ 76b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten switch (sfinfo->format & SF_FORMAT_TYPEMASK) { 77b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten case SF_FORMAT_WAV: 78b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten break; 79b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten default: 80b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return SL_BOOLEAN_FALSE; 81b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 82b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten switch (sfinfo->format & SF_FORMAT_SUBMASK) { 83276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten case SF_FORMAT_PCM_U8: 84b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten case SF_FORMAT_PCM_16: 85b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten break; 86b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten default: 87b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return SL_BOOLEAN_FALSE; 88b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 89b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten switch (sfinfo->samplerate) { 90276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten case 11025: 91276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten case 22050: 92b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten case 44100: 93b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten break; 94b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten default: 95b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return SL_BOOLEAN_FALSE; 96b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 97b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten switch (sfinfo->channels) { 98276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten case 1: 99b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten case 2: 100b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten break; 101b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten default: 102b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return SL_BOOLEAN_FALSE; 103b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 104b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return SL_BOOLEAN_TRUE; 105b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten} 106b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 107acd88797a1d3b8225bab888d29036e245f275be5Glenn KastenSLresult SndFile_checkAudioPlayerSourceSink(CAudioPlayer *this) 108daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten{ 109acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten const SLDataSource *pAudioSrc = &this->mDataSource.u.mSource; 110daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten SLuint32 locatorType = *(SLuint32 *)pAudioSrc->pLocator; 111daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten SLuint32 formatType = *(SLuint32 *)pAudioSrc->pFormat; 112daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten switch (locatorType) { 113daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten case SL_DATALOCATOR_BUFFERQUEUE: 114acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten this->mBufferQueue.mNumBuffers = 115acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten ((SLDataLocator_BufferQueue *) pAudioSrc->pLocator)->numBuffers; 116daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten break; 117daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten case SL_DATALOCATOR_URI: 118daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten { 119daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten SLDataLocator_URI *dl_uri = (SLDataLocator_URI *) pAudioSrc->pLocator; 120daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten SLchar *uri = dl_uri->URI; 121daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten if (NULL == uri) 122daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 12327f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten if (!strncmp((const char *) uri, "file:///", 8)) 12427f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten uri += 8; 125daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten switch (formatType) { 126daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten case SL_DATAFORMAT_MIME: 127daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten break; 128daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten default: 129daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten return SL_RESULT_CONTENT_UNSUPPORTED; 130daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten } 13127f8dfaea17ab7831a1bd34a02f85d55bacf67b7Glenn Kasten this->mSndFile.mPathname = uri; 13240d1c40832a448e23d0bb37512aee53222575c2eGlenn Kasten this->mBufferQueue.mNumBuffers = SndFile_NUMBUFS; 133daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten } 134daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten break; 135daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten default: 136daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten return SL_RESULT_CONTENT_UNSUPPORTED; 137daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten } 1386a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten this->mSndFile.mWhich = 0; 139acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten this->mSndFile.mSNDFILE = NULL; 140e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten // this->mSndFile.mMutex is initialized only when there is a valid mSNDFILE 141e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten this->mSndFile.mEOF = SL_BOOLEAN_FALSE; 142acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten this->mSndFile.mRetryBuffer = NULL; 143acd88797a1d3b8225bab888d29036e245f275be5Glenn Kasten this->mSndFile.mRetrySize = 0; 144daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten return SL_RESULT_SUCCESS; 145daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten} 146daf661248ff6ea2e21799e5114c78b7c1d49630eGlenn Kasten 147e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenvoid audioPlayerTransportUpdate(CAudioPlayer *audioPlayer) 148e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten{ 149e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten // marker and position updates here??? 150e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten SLmillisecond pos; 151e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten 152e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten pos = audioPlayer->mSeek.mPos; 153e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten audioPlayer->mSeek.mPos = SL_TIME_UNKNOWN; 154e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten 155e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten if ((SL_TIME_UNKNOWN != pos) && (NULL != audioPlayer->mSndFile.mSNDFILE)) { 156e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten pthread_mutex_lock(&audioPlayer->mSndFile.mMutex); 157e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten // FIXME use pos not 0 158e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten (void) sf_seek(audioPlayer->mSndFile.mSNDFILE, (sf_count_t) 0, SEEK_SET); 159e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten audioPlayer->mSndFile.mEOF = SL_BOOLEAN_FALSE; 160e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten pthread_mutex_unlock(&audioPlayer->mSndFile.mMutex); 161e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten } 162e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten 163e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten} 164e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten 165b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif // USE_SNDFILE 166