📄 rvorbis.cpp
字号:
// convert floats to 16bit signed ints (host order) and interleave for (i = 0; i < m_vi.channels; i++) { ogg_int16_t *ptr = ((ogg_int16_t*)audioData.pData->GetBuffer()) + i; float *mono = pcm[i]; for (j = 0; j < bout; j++) { int val = (int)(mono[j] * 32767.f); // guard against clipping if (val > 32767) { val = 32767; clipflag = 1; } if (val < -32768) { val = -32768; clipflag = 1; } *ptr = val; ptr += m_vi.channels; } } BOOL bWrite = AdjustAudioData(audioData); if (m_bIsGapInStreaming) { audioData.uAudioStreamType = TIMED_AUDIO; m_bIsGapInStreaming = FALSE; } else { audioData.uAudioStreamType = STREAMING_AUDIO; } if (bWrite) { ulLastWriteTime = audioData.ulAudioTime; HX_RESULT err = m_pCurrentStream->Write(&audioData); DPRINTF(D_VORBIS, ("write err 0x%08x samples %d audioTime %u\n", err, bout, audioData.ulAudioTime)); } } else { /* We failed to create a buffer so make it * look like there was a gap in the audio */ m_bIsGapInStreaming = TRUE; } HX_RELEASE(audioData.pData); m_totalSamples += bout; // tell vorbis how many samples we consumed vorbis_synthesis_read(&m_vd, bout); } return ulLastWriteTime;}void CVorbisRenderer::Shutdown(){ vorbis_comment_clear(&m_vc); vorbis_info_clear(&m_vi); HX_RELEASE(m_pContext); HX_RELEASE(m_pClassFactory); HX_RELEASE(m_pStream); HX_RELEASE(m_pPlayer); HX_RELEASE(m_pAudioPlayer); HX_RELEASE(m_pStreamHeaderObj); HX_RELEASE(m_pCurrentStream); while(!m_audioStreams.IsEmpty()) { COggAudioStreamHelper* pHlpr = (COggAudioStreamHelper*)m_audioStreams.RemoveHead(); pHlpr->Close(); HX_RELEASE(pHlpr); } HX_DELETE(m_pDepack);}void CVorbisRenderer::StartRebuffer(){ /* Only start a rebuffer if we have a stream * and we haven't had OnEndofPackets() called */ if (m_pStream && !m_bEndOfPackets) { DPRINTF(D_VORBIS,("Starting rebuffer\n")); m_bRebuffering = TRUE; m_pStream->ReportRebufferStatus(1, 0); }}void CVorbisRenderer::EndRebuffer(){ m_bRebuffering = FALSE; if (m_pStream) { DPRINTF(D_VORBIS,("Ending rebuffer\n")); m_pStream->ReportRebufferStatus(1, 1); }}int CVorbisRenderer::DepackInfoCount(){ return sizeof(zm_depackInfo) / sizeof(VorbisDepackInfo);}BOOL CVorbisRenderer::AdjustAudioData(REF(HXAudioData) audioData){ BOOL bResult = TRUE; UINT32 ulDuration = 0; UINT32 ulSize = 0; UINT32 ulExtraInMs = 0; UINT32 ulExtraInBytes = 0; IHXBuffer* pBuffer = NULL; ulSize = (audioData.pData)->GetSize(); // calculate the worth of this data in ms ulDuration = BytesToMs(ulSize); // trim off any extra bytes if (audioData.ulAudioTime < m_ulTrackStartTime) { if ((audioData.ulAudioTime + ulDuration) <= m_ulTrackStartTime) { bResult = FALSE; } else { // trim off partial data ulExtraInMs = m_ulTrackStartTime - audioData.ulAudioTime; // convert to bytes ulExtraInBytes = MsToBytes(ulExtraInMs); // align in sample boundary ulExtraInBytes -= (ulExtraInBytes % (m_audioFmt.uBitsPerSample * m_audioFmt.uChannels / 8)); if (!m_pClassFactory || HXR_OK != m_pClassFactory->CreateInstance( CLSID_IHXBuffer, (void**)&pBuffer)) { bResult = FALSE; } else { pBuffer->Set((audioData.pData)->GetBuffer() + ulExtraInBytes, ulSize - ulExtraInBytes); //Release and replace with new buffer: HX_RELEASE(audioData.pData); audioData.pData = pBuffer; audioData.ulAudioTime = m_ulTrackStartTime; } } } if (bResult && (m_ulTrackEndTime != NO_TIME_SET) && (audioData.ulAudioTime + ulDuration) > m_ulTrackEndTime) { if (audioData.ulAudioTime >= m_ulTrackEndTime) { // drop this one bResult = FALSE; } else { // trim off the extra ones ulExtraInMs = (audioData.ulAudioTime + ulDuration) - m_ulTrackEndTime; // convert to bytes ulExtraInBytes = MsToBytes(ulExtraInMs); // align in sample boundary ulExtraInBytes -= (ulExtraInBytes % (m_audioFmt.uBitsPerSample * m_audioFmt.uChannels / 8)); if (!m_pClassFactory || HXR_OK != m_pClassFactory->CreateInstance( CLSID_IHXBuffer, (void**)&pBuffer)) { bResult = FALSE; } else { pBuffer->Set((audioData.pData)->GetBuffer(), ulSize - ulExtraInBytes); //Release and replace with new buffer: HX_RELEASE(audioData.pData); audioData.pData = pBuffer; } } } if (bResult) { if (m_lTimeOffset < 0) { audioData.ulAudioTime += (UINT32) (-m_lTimeOffset); } else { //HX_ASSERT(audioData.ulAudioTime >= (UINT32)m_lTimeOffset); audioData.ulAudioTime -= (UINT32)m_lTimeOffset; } } return bResult;}void CVorbisRenderer::updateBitrateInfo(vorbis_info* vi){ if (vi && m_pStream && m_pContext) { INT32 clipBitrate = 0; if (vi->bitrate_nominal > 0) { clipBitrate = vi->bitrate_nominal; } else if (vi->bitrate_upper > 0) { clipBitrate = vi->bitrate_upper; } UINT32 uStreamRegID; IHXRegistry* pReg = NULL; if ((HXR_OK == getRegistryID(m_pStream, uStreamRegID)) && (HXR_OK == m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pReg))) { CHXString propName; if ((clipBitrate > 0) && (HXR_OK == getPropName(uStreamRegID, "ClipBandwidth", propName))) { pReg->SetIntByName(propName, clipBitrate); } } HX_RELEASE(pReg); }}void CVorbisRenderer::updateTACInfo(vorbis_comment* vc){ if (vc && m_pStream && m_pContext) { IHXStreamSource* pStreamSrc = NULL; IHXRegistry* pReg = NULL; UINT32 uSourceRegID; if ((HXR_OK == m_pStream->GetSource(pStreamSrc)) && (HXR_OK == getRegistryID(pStreamSrc, uSourceRegID)) && (HXR_OK == m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pReg))) { int tagInfoCount = sizeof(zm_tagInfo) / sizeof(VorbisTagMapping); for (int i = 0; i < tagInfoCount; i++) { char* pVorbisTag = zm_tagInfo[i].m_pVorbisTag; const char* pPropName = zm_tagInfo[i].m_pPropName; int commentCount = vorbis_comment_query_count(vc, pVorbisTag); if (commentCount > 0) { CHXString value = vorbis_comment_query(vc, pVorbisTag, 0); for (int j = 1; j < commentCount; j++) { value += ", "; value += vorbis_comment_query(vc, pVorbisTag, j); } IHXBuffer* pPropValBuf = NULL; if (HXR_OK == CreateStringBuffer(pPropValBuf, value, m_pContext)) { CHXString propName; if (HXR_OK == getPropName(uSourceRegID, pPropName, propName)) { pReg->SetStrByName(propName, pPropValBuf); } } HX_RELEASE(pPropValBuf); } } } HX_RELEASE(pStreamSrc); HX_RELEASE(pReg); }}HX_RESULT CVorbisRenderer::getPropName(UINT32 uBaseID, const char* pChildPropName, CHXString& propName){ HX_RESULT res = HXR_INVALID_PARAMETER; if (!m_pContext) { res = HXR_UNEXPECTED; } else if (pChildPropName && strlen(pChildPropName)) { IHXRegistry* pReg = NULL; IHXBuffer* pBasePropName = NULL; res = m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pReg); if (HXR_OK == res) { res = pReg->GetPropName(uBaseID, pBasePropName); } if (HXR_OK == res) { propName = (const char*)pBasePropName->GetBuffer(); propName += '.'; propName += pChildPropName; } HX_RELEASE(pReg); HX_RELEASE(pBasePropName); } return res;}HX_RESULT CVorbisRenderer::getRegistryID(IUnknown* pUnk, REF(UINT32) uRegID){ HX_RESULT res = HXR_INVALID_PARAMETER; if (pUnk) { IHXRegistryID* pRegID = NULL; res = pUnk->QueryInterface(IID_IHXRegistryID, (void**)&pRegID); if (HXR_OK == res) { res = pRegID->GetID(uRegID); } HX_RELEASE(pRegID); } return res;}void CVorbisRenderer::gotoInitialHeaderState(){ vorbis_comment_clear(&m_vc); vorbis_info_clear(&m_vi); vorbis_info_init(&m_vi); vorbis_comment_init(&m_vc); m_VorbisState = VorbisInitialHeader;}HX_RESULT CVorbisRenderer::handleInitialHeader(ogg_packet* pOp){ HX_RESULT res = HXR_FAILED; if (vorbis_synthesis_headerin(&m_vi, &m_vc, pOp) >= 0) { DPRINTF(D_VORBIS,("Got Initial Header\n")); updateBitrateInfo(&m_vi); /* check to see if the audio format is different * from the default values */ if ((m_audioFmt.uChannels != m_vi.channels) || (m_audioFmt.ulSamplesPerSec != (UINT32)m_vi.rate)) { /* The parameters are different. * Release our handle on the current stream * and create a new audio stream object. */ res = InitAudioStream(m_vi.rate, m_vi.channels); m_bIsGapInStreaming = TRUE; } else { m_pCurrentStream->SetDryNotification(this); res = HXR_OK; } m_VorbisState = VorbisCommentHeader; } else { HX_ASSERT(FALSE); } return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -