iOS音乐播放器实现代码完整版
本文实例为大家分享了iOS实现音乐播放器的具体代码,供大家参考,具体内容如下
audio_queue.cpp
/* *ThisfileispartoftheFreeStreamerproject, *(C)Copyright2011-2013MatiasMuhonen. *Seethefile''LICENSE''forusingthecode. * *Partofthecodeinthisfilehasbeenrewrittenfrom *theAudioFileStreamExample/afsclient.cpp *example,Copyright©2007AppleInc. * *Thethreadlessplaybackhasbeenadaptedfrom *AlexCrichton'sAudioStreamer. */ #include"audio_queue.h" #include//#defineAQ_DEBUG1 #if!defined(AQ_DEBUG) #defineAQ_TRACE(...)do{}while(0) #else #defineAQ_TRACE(...)printf(__VA_ARGS__) #endif namespaceastreamer{ typedefstructqueued_packet{ AudioStreamPacketDescriptiondesc; structqueued_packet*next; chardata[]; }queued_packet_t; /*public*/ Audio_Queue::Audio_Queue() :m_delegate(0), m_state(IDLE), m_outAQ(0), m_fillBufferIndex(0), m_bytesFilled(0), m_packetsFilled(0), m_buffersUsed(0), m_processedPacketsSizeTotal(0), m_processedPacketsCount(0), m_audioQueueStarted(false), m_waitingOnBuffer(false), m_queuedHead(0), m_queuedTail(0), m_lastError(noErr) { for(size_ti=0;i packetDuration(); if(packetDuration>0&&m_processedPacketsCount>50){ doubleaveragePacketByteSize=m_processedPacketsSizeTotal/m_processedPacketsCount; bitrate=8*averagePacketByteSize/packetDuration; } returnbitrate; } voidAudio_Queue::handlePropertyChange(AudioFileStreamIDinAudioFileStream,AudioFileStreamPropertyIDinPropertyID,UInt32*ioFlags) { OSStatuserr=noErr; AQ_TRACE("foundproperty'%lu%lu%lu%lu'\n",(inPropertyID>>24)&255,(inPropertyID>>16)&255,(inPropertyID>>8)&255,inPropertyID&255); switch(inPropertyID){ casekAudioFileStreamProperty_ReadyToProducePackets: { cleanup(); //thefilestreamparserisnowreadytoproduceaudiopackets. //getthestreamformat. memset(&m_streamDesc,0,sizeof(m_streamDesc)); UInt32asbdSize=sizeof(m_streamDesc); err=AudioFileStreamGetProperty(inAudioFileStream,kAudioFileStreamProperty_DataFormat,&asbdSize,&m_streamDesc); if(err){ AQ_TRACE("%s:errorinkAudioFileStreamProperty_DataFormat\n",__PRETTY_FUNCTION__); m_lastError=err; break; } //createtheaudioqueue err=AudioQueueNewOutput(&m_streamDesc,audioQueueOutputCallback,this,CFRunLoopGetCurrent(),NULL,0,&m_outAQ); if(err){ AQ_TRACE("%s:errorinAudioQueueNewOutput\n",__PRETTY_FUNCTION__); if(m_delegate){ m_delegate->audioQueueInitializationFailed(); } m_lastError=err; break; } //allocateaudioqueuebuffers for(unsignedinti=0;i audioQueueInitializationFailed(); } m_lastError=err; break; } } setCookiesForStream(inAudioFileStream); //listenforkAudioQueueProperty_IsRunning err=AudioQueueAddPropertyListener(m_outAQ,kAudioQueueProperty_IsRunning,audioQueueIsRunningCallback,this); if(err){ AQ_TRACE("%s:errorinAudioQueueAddPropertyListener\n",__PRETTY_FUNCTION__); m_lastError=err; break; } break; } } } voidAudio_Queue::handleAudioPackets(UInt32inNumberBytes,UInt32inNumberPackets,constvoid*inInputData,AudioStreamPacketDescription*inPacketDescriptions) { if(!initialized()){ AQ_TRACE("%s:warning:attempttohandleaudiopacketswithuninitializedaudioqueue.return.\n",__PRETTY_FUNCTION__); return; } //thisiscalledbyaudiofilestreamwhenitfindspacketsofaudio AQ_TRACE("gotdata.bytes:%lupackets:%lu\n",inNumberBytes,inNumberPackets); /*Placeeachpacketintoabufferandthensendeachbufferintotheaudio queue*/ UInt32i; if(!inPacketDescriptions){ AQ_TRACE("%s:notice:supplyingthepacketdescriptionsforasupposedCBRdata.\n",__PRETTY_FUNCTION__); //Ifnopacketdescriptionsaresupplied,assumewearedealingwithCBRdata UInt32base=inNumberBytes/inNumberPackets; AudioStreamPacketDescription*descriptions=newAudioStreamPacketDescription[inNumberPackets]; for(i=0;i mStartOffset,desc); if(!ret)break; } if(i==inNumberPackets){ return; } for(;i next=NULL; packet->desc=inPacketDescriptions[i]; packet->desc.mStartOffset=0; memcpy(packet->data,(constchar*)inInputData+inPacketDescriptions[i].mStartOffset, size); if(m_queuedHead==NULL){ m_queuedHead=m_queuedTail=packet; }else{ m_queuedTail->next=packet; m_queuedTail=packet; } } } intAudio_Queue::handlePacket(constvoid*data,AudioStreamPacketDescription*desc) { if(!initialized()){ AQ_TRACE("%s:warning:attempttohandleaudiopacketswithuninitializedaudioqueue.return.\n",__PRETTY_FUNCTION__); return-1; } AQ_TRACE("%s:enter\n",__PRETTY_FUNCTION__); UInt32packetSize=desc->mDataByteSize; /*Thisshouldn'thappenbecausemostofthetimewereadthepacketbuffer sizefromthefilestream,butifwerestoredtoguessingitwecould comeuptoosmallhere*/ if(packetSize>AQ_BUFSIZ){ AQ_TRACE("%s:packetSize%lli>AQ_BUFSIZ%li\n",__PRETTY_FUNCTION__,packetSize,AQ_BUFSIZ); return-1; } //ifthespaceremaininginthebufferisnotenoughforthispacket,then //enqueuethebufferandwaitforanothertobecomeavailable. if(AQ_BUFSIZ-m_bytesFilled mAudioData+m_bytesFilled,data,packetSize); //filloutpacketdescriptiontopasstoenqueue()lateron m_packetDescs[m_packetsFilled]=*desc; //Makesuretheoffsetisrelativetothestartoftheaudiobuffer m_packetDescs[m_packetsFilled].mStartOffset=m_bytesFilled; //keeptrackofbytesfilledandpacketsfilled m_bytesFilled+=packetSize; m_packetsFilled++; /*Maximumnumberofpacketswhichcanbecontainedinonebuffer*/ #definekAQMaxPacketDescs512 /*Iffilledourbufferwithpackets,thencommitittothesystem*/ if(m_packetsFilled>=kAQMaxPacketDescs){ returnenqueueBuffer(); } return1; } /*private*/ voidAudio_Queue::cleanup() { if(!initialized()){ AQ_TRACE("%s:warning:attempttocleanupanuninitializedaudioqueue.return.\n",__PRETTY_FUNCTION__); return; } if(AudioQueueDispose(m_outAQ,true)!=0){ AQ_TRACE("%s:AudioQueueDisposefailed!\n",__PRETTY_FUNCTION__); } m_outAQ=0; m_fillBufferIndex=m_bytesFilled=m_packetsFilled=m_buffersUsed=m_processedPacketsSizeTotal=m_processedPacketsCount=0; for(size_ti=0;i next; free(cur); cur=tmp; } m_queuedHead=m_queuedHead=0; for(size_ti=0;i audioQueueStateChanged(m_state); } } intAudio_Queue::enqueueBuffer() { assert(!m_bufferInUse[m_fillBufferIndex]); AQ_TRACE("%s:enter\n",__PRETTY_FUNCTION__); m_bufferInUse[m_fillBufferIndex]=true; m_buffersUsed++; //enqueuebuffer AudioQueueBufferReffillBuf=m_audioQueueBuffer[m_fillBufferIndex]; fillBuf->mAudioDataByteSize=m_bytesFilled; assert(m_packetsFilled>0); OSStatuserr=AudioQueueEnqueueBuffer(m_outAQ,fillBuf,m_packetsFilled,m_packetDescs); if(!err){ m_lastError=noErr; start(); }else{ /*Ifwegetanerrorhere,itverylikelymeansthattheaudioqueueisnolonger running*/ AQ_TRACE("%s:errorinAudioQueueEnqueueBuffer\n",__PRETTY_FUNCTION__); m_lastError=err; return1; } //gotonextbuffer if(++m_fillBufferIndex>=AQ_BUFFERS){ m_fillBufferIndex=0; } //resetbytesfilled m_bytesFilled=0; //resetpacketsfilled m_packetsFilled=0; //waituntilnextbufferisnotinuse if(m_bufferInUse[m_fillBufferIndex]){ AQ_TRACE("waitingforbuffer%lu\n",m_fillBufferIndex); if(m_delegate){ m_delegate->audioQueueOverflow(); } m_waitingOnBuffer=true; return0; } return1; } intAudio_Queue::findQueueBuffer(AudioQueueBufferRefinBuffer) { for(unsignedinti=0;i data,&cur->desc); if(ret==0){ break; } queued_packet_t*next=cur->next; free(cur); cur=next; } m_queuedHead=cur; /*Ifwefinishedqueueingalloursavedpackets,wecanre-schedulethe *streamtorun*/ if(cur==NULL){ m_queuedTail=NULL; if(m_delegate){ m_delegate->audioQueueUnderflow(); } } } //thisiscalledbytheaudioqueuewhenithasfinisheddecodingourdata. //Thebufferisnowfreetobereused. voidAudio_Queue::audioQueueOutputCallback(void*inClientData,AudioQueueRefinAQ,AudioQueueBufferRefinBuffer) { Audio_Queue*audioQueue=static_cast (inClientData); unsignedintbufIndex=audioQueue->findQueueBuffer(inBuffer); assert(audioQueue->m_bufferInUse[bufIndex]); audioQueue->m_bufferInUse[bufIndex]=false; audioQueue->m_buffersUsed--; if(audioQueue->m_buffersUsed==0&&!audioQueue->m_queuedHead&&audioQueue->m_delegate){ audioQueue->m_delegate->audioQueueBuffersEmpty(); }elseif(audioQueue->m_waitingOnBuffer){ audioQueue->m_waitingOnBuffer=false; audioQueue->enqueueCachedData(); } } voidAudio_Queue::audioQueueIsRunningCallback(void*inClientData,AudioQueueRefinAQ,AudioQueuePropertyIDinID) { Audio_Queue*audioQueue=static_cast (inClientData); AQ_TRACE("%s:enter\n",__PRETTY_FUNCTION__); UInt32running; UInt32output=sizeof(running); OSStatuserr=AudioQueueGetProperty(inAQ,kAudioQueueProperty_IsRunning,&running,&output); if(err){ AQ_TRACE("%s:errorinkAudioQueueProperty_IsRunning\n",__PRETTY_FUNCTION__); return; } if(running){ AQ_TRACE("audioqueuerunning!\n"); audioQueue->setState(RUNNING); }else{ audioQueue->setState(IDLE); } } }//namespaceastreamer
audio_stream.h
/* *ThisfileispartoftheFreeStreamerproject, *(C)Copyright2011-2013MatiasMuhonen. *Seethefile''LICENSE''forusingthecode. */ #ifndefASTREAMER_AUDIO_STREAM_H #defineASTREAMER_AUDIO_STREAM_H #import"http_stream.h" #include"audio_queue.h" #include#include namespaceastreamer{ enumAudio_Stream_Error{ AS_ERR_OPEN=1,//Cannotopentheaudiostream AS_ERR_STREAM_PARSE=2,//Parseerror AS_ERR_NETWORK=3//Networkerror }; classAudio_Stream_Delegate; classAudio_Stream:publicHTTP_Stream_Delegate,publicAudio_Queue_Delegate{ public: Audio_Stream_Delegate*m_delegate; enumState{ STOPPED, BUFFERING, PLAYING, SEEKING, FAILED, END_OF_FILE }; Audio_Stream(); virtual~Audio_Stream(); voidopen(); voidclose(); voidpause(); unsignedtimePlayedInSeconds(); unsigneddurationInSeconds(); voidseekToTime(unsignednewSeekTime); voidsetUrl(CFURLRefurl); voidsetStrictContentTypeChecking(boolstrictChecking); voidsetDefaultContentType(std::string&defaultContentType); Statestate(); /*Audio_Queue_Delegate*/ voidaudioQueueStateChanged(Audio_Queue::Statestate); voidaudioQueueBuffersEmpty(); voidaudioQueueOverflow(); voidaudioQueueUnderflow(); voidaudioQueueInitializationFailed(); /*HTTP_Stream_Delegate*/ voidstreamIsReadyRead(); voidstreamHasBytesAvailable(UInt8*data,UInt32numBytes); voidstreamEndEncountered(); voidstreamErrorOccurred(); voidstreamMetaDataAvailable(std::map metaData); private: Audio_Stream(constAudio_Stream&); Audio_Stream&operator=(constAudio_Stream&); boolm_httpStreamRunning; boolm_audioStreamParserRunning; size_tm_contentLength; Statem_state; HTTP_Stream*m_httpStream; Audio_Queue*m_audioQueue; AudioFileStreamIDm_audioFileStream;//theaudiofilestreamparser SInt64m_dataOffset; unsignedm_seekTime; boolm_strictContentTypeChecking; std::stringm_defaultContentType; size_tcontentLength(); voidcloseAndSignalError(interror); voidsetState(Statestate); staticvoidpropertyValueCallback(void*inClientData,AudioFileStreamIDinAudioFileStream,AudioFileStreamPropertyIDinPropertyID,UInt32*ioFlags); staticvoidstreamDataCallback(void*inClientData,UInt32inNumberBytes,UInt32inNumberPackets,constvoid*inInputData,AudioStreamPacketDescription*inPacketDescriptions); AudioFileTypeIDaudioStreamTypeFromContentType(std::stringcontentType); }; classAudio_Stream_Delegate{ public: virtualvoidaudioStreamStateChanged(Audio_Stream::Statestate)=0; virtualvoidaudioStreamErrorOccurred(interrorCode)=0; virtualvoidaudioStreamMetaDataAvailable(std::map metaData)=0; }; }//namespaceastreamer #endif//ASTREAMER_AUDIO_STREAM_H
更多源码请点击下载:iOS音乐播放器实现代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。