STDMETHODIMP CSynthFilter::put_OutputFormat(SYNTH_OUTPUT_FORMAT ofOutputFormat) { // This function holds the state lock because it does not want // the filter's format type state or its' connection state // to change between the call to put_OutputFormat() and the call to // ReconnectWithNewFormat(). CAutoLock lStateLock(pStateLock()); HRESULT hr = m_Synth->put_OutputFormat(ofOutputFormat); if (FAILED(hr)) { return hr; } ReconnectWithNewFormat(); return S_OK; }
// // put_SamplesPerSec // STDMETHODIMP CSynthFilter::put_SamplesPerSec(int SamplesPerSec) { // This function holds the state lock because it does not want // the filter's format type state or its' connection state // to change between the call to put_SamplesPerSec() and the call to // ReconnectWithNewFormat(). CAutoLock lStateLock(pStateLock()); HRESULT hr = m_Synth->put_SamplesPerSec(SamplesPerSec); if( FAILED( hr ) ) { return hr; } ReconnectWithNewFormat (); DbgLog((LOG_TRACE, 3, TEXT("put_SamplesPerSec: %d"), SamplesPerSec)); return NOERROR; }
// // FillBuffer // // Stuffs the buffer with data HRESULT CSynthStream::FillBuffer(IMediaSample *pms) { CheckPointer(pms,E_POINTER); BYTE *pData; HRESULT hr = pms->GetPointer(&pData); if (FAILED(hr)) { return hr; } // This function must hold the state lock because it calls // FillPCMAudioBuffer(). CAutoLock lStateLock(m_pParent->pStateLock()); // This lock must be held because this function uses // m_dwTempPCMBufferSize, m_hPCMToMSADPCMConversionStream, // m_rtSampleTime, m_fFirstSampleDelivered and // m_llSampleMediaTimeStart. CAutoLock lShared(&m_cSharedState); WAVEFORMATEX* pwfexCurrent = (WAVEFORMATEX*)m_mt.Format(); if (WAVE_FORMAT_PCM == pwfexCurrent->wFormatTag) { m_Synth->FillPCMAudioBuffer(*pwfexCurrent, pData, pms->GetSize()); hr = pms->SetActualDataLength(pms->GetSize()); if (FAILED(hr)) return hr; } else { // This filter only supports two audio formats: PCM and ADPCM. ASSERT(WAVE_FORMAT_ADPCM == pwfexCurrent->wFormatTag); // Create PCM audio samples and then compress them. We use the // Audio Compression Manager (ACM) API to convert the samples to // the ADPCM format. ACMSTREAMHEADER ACMStreamHeader; ACMStreamHeader.cbStruct = sizeof(ACMStreamHeader); ACMStreamHeader.fdwStatus = 0; ACMStreamHeader.dwUser = 0; ACMStreamHeader.cbSrcLength = m_dwTempPCMBufferSize; ACMStreamHeader.cbSrcLengthUsed = 0; ACMStreamHeader.dwSrcUser = 0; ACMStreamHeader.pbDst = pData; ACMStreamHeader.cbDstLength = pms->GetSize(); ACMStreamHeader.cbDstLengthUsed = 0; ACMStreamHeader.dwDstUser = 0; ACMStreamHeader.pbSrc = new BYTE[m_dwTempPCMBufferSize]; if (NULL == ACMStreamHeader.pbSrc) { return E_OUTOFMEMORY; } WAVEFORMATEX wfexPCMAudio; DerivePCMFormatFromADPCMFormatStructure(*pwfexCurrent, &wfexPCMAudio); m_Synth->FillPCMAudioBuffer(wfexPCMAudio, ACMStreamHeader.pbSrc, ACMStreamHeader.cbSrcLength); MMRESULT mmr = acmStreamPrepareHeader(m_hPCMToMSADPCMConversionStream, &ACMStreamHeader, 0); // acmStreamPrepareHeader() returns 0 if no errors occur. if (mmr != 0) { delete [] ACMStreamHeader.pbSrc; return E_FAIL; } mmr = acmStreamConvert(m_hPCMToMSADPCMConversionStream, &ACMStreamHeader, ACM_STREAMCONVERTF_BLOCKALIGN); MMRESULT mmrUnprepare = acmStreamUnprepareHeader(m_hPCMToMSADPCMConversionStream, &ACMStreamHeader, 0); delete [] ACMStreamHeader.pbSrc; // acmStreamConvert() andacmStreamUnprepareHeader() returns 0 if no errors occur. if ((mmr != 0) || (mmrUnprepare != 0)) { return E_FAIL; } hr = pms->SetActualDataLength(ACMStreamHeader.cbDstLengthUsed); if (FAILED(hr)) { return hr; } } // Set the sample's time stamps. CRefTime rtStart = m_rtSampleTime; m_rtSampleTime = rtStart + (REFERENCE_TIME)(UNITS * pms->GetActualDataLength()) / (REFERENCE_TIME)pwfexCurrent->nAvgBytesPerSec; hr = pms->SetTime((REFERENCE_TIME*)&rtStart, (REFERENCE_TIME*)&m_rtSampleTime); if (FAILED(hr)) { return hr; } // Set the sample's properties. hr = pms->SetPreroll(FALSE); if (FAILED(hr)) { return hr; } hr = pms->SetMediaType(NULL); if (FAILED(hr)) { return hr; } hr = pms->SetDiscontinuity(!m_fFirstSampleDelivered); if (FAILED(hr)) { return hr; } hr = pms->SetSyncPoint(!m_fFirstSampleDelivered); if (FAILED(hr)) { return hr; } LONGLONG llMediaTimeStart = m_llSampleMediaTimeStart; DWORD dwNumAudioSamplesInPacket = (pms->GetActualDataLength() * BITS_PER_BYTE) / (pwfexCurrent->nChannels * pwfexCurrent->wBitsPerSample); LONGLONG llMediaTimeStop = m_llSampleMediaTimeStart + dwNumAudioSamplesInPacket; hr = pms->SetMediaTime(&llMediaTimeStart, &llMediaTimeStop); if (FAILED(hr)) { return hr; } m_llSampleMediaTimeStart = llMediaTimeStop; m_fFirstSampleDelivered = TRUE; return NOERROR; }