/** * * SoundTouch.ax * 作成者: id:yuaaaa * ほんとはGPLっていわなきゃいけない * * $Id$ */ #include "main.h" const AMOVIESETUP_MEDIATYPE sudPinTypes = { &MEDIATYPE_Audio // clsMajorType , &MEDIASUBTYPE_PCM }; // clsMinorType const AMOVIESETUP_PIN psudPins[] = { { L"Input" // strName , FALSE // bRendered , FALSE // bOutput , FALSE // bZero , FALSE // bMany , &CLSID_NULL // clsConnectsToFilter , L"Output" // strConnectsToPin , 1 // nTypes , &sudPinTypes // lpTypes } , { L"Output" // strName , FALSE // bRendered , TRUE // bOutput , FALSE // bZero , FALSE // bMany , &CLSID_NULL // clsConnectsToFilter , L"Input" // strConnectsToPin , 1 // nTypes , &sudPinTypes // lpTypes } }; const AMOVIESETUP_FILTER sudSoundTouch = { &CLSID_SoundTouch // class id #ifdef _DEBUG , L"SoundTouch (debug)" // strName #else , L"SoundTouch" // strName #endif , MERIT_DO_NOT_USE // dwMerit , 2 // nPins , psudPins // lpPin }; const AMOVIESETUP_FILTER sudSoundTouch_Auto = { &CLSID_SoundTouch_AUTOLOAD // class id #ifdef _DEBUG , L"SoundTouch (debug) (auto-JoyHack version)" // strName #else , L"SoundTouch (auto-JoyHack version)" // strName #endif , 0x00800002 // dwMerit , 2 // nPins , psudPins // lpPin }; // Needed for the CreateInstance mechanism CFactoryTemplate g_Templates[3]= { { L"SoundTouch" , &CLSID_SoundTouch , CSoundTouch::CreateInstance , NULL , &sudSoundTouch } , { L"SoundTouch (auto-JoyHack version)" , &CLSID_SoundTouch_AUTOLOAD , CSoundTouch_AutoJoy::CreateInstance , NULL , &sudSoundTouch_Auto } , { L"SoundTouch Property Page" , &CLSID_SoundTouchProp , CSoundTouchProperties::CreateInstance } }; int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]); // initialise the static instance count. int CSoundTouch::m_nInstanceCount = 0; CSoundTouch::CSoundTouch(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) : CTransInPlaceFilter (tszName, punk, CLSID_SoundTouch, phr) , CPersistStream(punk, phr) , m_SamplesPerSec (0) , m_BytesPerSample (0) , m_Channels (0) , m_Key (0) , m_Speed (1.0f) , m_Enable (true) { m_nThisInstance = ++m_nInstanceCount; return; } CUnknown * WINAPI CSoundTouch::CreateInstance(LPUNKNOWN punk, HRESULT *phr) { ASSERT(phr); CSoundTouch *pNewObject = new CSoundTouch(NAME("SoundTouch Filter"), punk, phr); if (pNewObject == NULL) { if (phr) *phr = E_OUTOFMEMORY; } return pNewObject; } STDMETHODIMP CSoundTouch::NonDelegatingQueryInterface(REFIID riid, void **ppv) { CheckPointer(ppv,E_POINTER); if (riid == IID_ISoundTouch) { return GetInterface((ISoundTouch *) this, ppv); } else if (riid == IID_ISpecifyPropertyPages) { return GetInterface((ISpecifyPropertyPages *) this, ppv); } else if (riid == IID_IPersistStream) { return GetInterface((IPersistStream *) this, ppv); } else { // Pass the buck return CTransformFilter::NonDelegatingQueryInterface(riid, ppv); } } STDMETHODIMP CSoundTouch::GetClassID(CLSID *pClsid) { CheckPointer(pClsid,E_POINTER); *pClsid = CLSID_SoundTouch; return NOERROR; } int CSoundTouch::SizeMax() { return 48; } void CSoundTouch::MessItAbout(PBYTE pb, int cb, int *retsize) { CAutoLock foo(&m_SoundTouchLock); // We know how many samples per sec and how // many channels so we can calculate the modulation period in samples. // int buffSizeSamples = cb/sizeof(soundtouch::SAMPLETYPE)/m_Channels; SoundTouch.putSamples( (soundtouch::SAMPLETYPE*)pb, buffSizeSamples ); uint OKSamples; OKSamples = SoundTouch.numSamples(); uint nSamples, allsamples = 0; nSamples = SoundTouch.receiveSamples((soundtouch::SAMPLETYPE*)pb, buffSizeSamples); allsamples += nSamples; *retsize = allsamples * sizeof(soundtouch::SAMPLETYPE) * m_Channels; } // MessItAbout HRESULT CSoundTouch::Transform(IMediaSample *pSample) { CheckPointer( pSample, E_POINTER ); BYTE *pSampleBuffer; int iSize = pSample->GetActualDataLength(); pSample->GetPointer(&pSampleBuffer); if ( m_Enable ) { int procedsize; MessItAbout(pSampleBuffer, iSize, &procedsize ); HRESULT hr; hr = pSample->SetActualDataLength(procedsize); if (FAILED(hr)) { OutputDebugString(TEXT("FAILED...\n")); return hr; } } return S_OK; } HRESULT CSoundTouch::CheckInputType(const CMediaType *pmt) { CheckPointer(pmt,E_POINTER); WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pmt->pbFormat; CheckPointer(pwfx, VFW_E_TYPE_NOT_ACCEPTED); // Reject non-Audio types. // if (pmt->majortype != MEDIATYPE_Audio) { return VFW_E_TYPE_NOT_ACCEPTED; } if (pmt->subtype != MEDIASUBTYPE_PCM) { return VFW_E_TYPE_NOT_ACCEPTED; } // Reject invalid format blocks // if (pmt->formattype != FORMAT_WaveFormatEx) return VFW_E_TYPE_NOT_ACCEPTED; // Reject compressed audio // if (pwfx->wFormatTag != WAVE_FORMAT_PCM) { return VFW_E_TYPE_NOT_ACCEPTED; } // Accept only 16 bit // if (pwfx->wBitsPerSample!=16) { //FIXME return VFW_E_TYPE_NOT_ACCEPTED; } return NOERROR; } HRESULT CSoundTouch::GetMediaType(int iPosition, CMediaType *pMediaType) { CheckPointer( pMediaType, E_POINTER ); if ( iPosition < 0 ) { return E_INVALIDARG; } if ( iPosition > 0 ) { return VFW_S_NO_MORE_ITEMS; } pMediaType->AllocFormatBuffer( sizeof( WAVEFORMATEX ) ); WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pMediaType->pbFormat; //ZeroMemory(pwfx, sizeof( WAVEFORMATEX )); pMediaType->majortype = MEDIATYPE_Audio; pMediaType->subtype = MEDIASUBTYPE_PCM; pMediaType->formattype = FORMAT_WaveFormatEx; pwfx->wFormatTag = WAVE_FORMAT_PCM; pwfx->wBitsPerSample = 16; pwfx->nSamplesPerSec = m_SamplesPerSec; pwfx->wBitsPerSample = m_BytesPerSample*8; pwfx->nChannels = m_Channels; pwfx->nAvgBytesPerSec = m_AvgBytesPerSec; pwfx->nBlockAlign = m_BlockAlign; pwfx->cbSize = 0; return S_OK; } HRESULT CSoundTouch::SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt) { if ( direction != PINDIR_INPUT ) { return NO_ERROR; } CheckPointer(pmt,E_POINTER); // Record what we need for doing the actual transform WAVEFORMATEX *pwfx = (WAVEFORMATEX *) pmt->Format(); m_Channels = pwfx->nChannels; m_SamplesPerSec = pwfx->nSamplesPerSec; m_AvgBytesPerSec = pwfx->nAvgBytesPerSec; m_BlockAlign = pwfx->nBlockAlign; m_BytesPerSample = pwfx->wBitsPerSample/8; SoundTouch.setSampleRate(m_SamplesPerSec); SoundTouch.setChannels(m_Channels); put_TouchKey(0); SoundTouch.setSetting(SETTING_USE_QUICKSEEK, 0); // Call the base class to do its thing CTransformFilter::SetMediaType(direction, pmt); // Reconnect where necessary. if( m_pInput->IsConnected() && m_pOutput->IsConnected() ) { FILTER_INFO fInfo; QueryFilterInfo( &fInfo ); if (direction == PINDIR_OUTPUT && *pmt != m_pInput->CurrentMediaType() ) fInfo.pGraph->Reconnect( m_pInput ); QueryFilterInfoReleaseGraph( fInfo ); //ASSERT(!(direction == PINDIR_INPUT && *pmt != m_pOutput->CurrentMediaType())); } return NOERROR; } void CSoundTouch::Setup_Pitch ( void ) { SoundTouch.setPitch( ( (float)exp( 0.69314718056f * ((float)m_Key / 12.0f) ) ) / m_Speed ); CPersistStream::SetDirty(TRUE); } HRESULT CSoundTouch::Setup_GraphRate(void) { if ( m_pGraph == NULL ) { return E_POINTER; } IMediaSeeking *pMS = NULL; m_pGraph->QueryInterface( &pMS ); if ( pMS == NULL ) { return E_FAIL; } return pMS->SetRate( this->m_Speed ); } //Interface STDMETHODIMP CSoundTouch::get_TouchKey( int *pkey ) { CheckPointer(pkey,E_POINTER); CAutoLock foo(&m_SoundTouchLock); *pkey = m_Key; return NOERROR; } STDMETHODIMP CSoundTouch::put_TouchKey ( int key ) { if ( ! ( -60 <= key && key <= 60 ) ) { return E_INVALIDARG; } CAutoLock foo(&m_SoundTouchLock); m_Key = key; Setup_Pitch(); return NOERROR; } STDMETHODIMP CSoundTouch::get_Speed (float *pspeed) { CheckPointer(pspeed,E_POINTER); CAutoLock foo(&m_SoundTouchLock); *pspeed = m_Speed; return NOERROR; } STDMETHODIMP CSoundTouch::put_Speed (float speed) { if ( ! ( 0.05f <= speed && speed <= 50.0f ) ) { return E_INVALIDARG; } CAutoLock foo(&m_SoundTouchLock); m_Speed = speed; Setup_Pitch(); return NOERROR; } STDMETHODIMP CSoundTouch::get_Setting( uint id, uint *pparam ) { CheckPointer(pparam,E_POINTER); CAutoLock foo(&m_SoundTouchLock); *pparam = SoundTouch.getSetting( id ); return NOERROR; } STDMETHODIMP CSoundTouch::put_Setting ( uint id, uint param ) { CAutoLock foo(&m_SoundTouchLock); SoundTouch.setSetting ( id, param ); CPersistStream::SetDirty(TRUE); return NOERROR; } STDMETHODIMP CSoundTouch::get_Enable( bool *penable ) { CheckPointer(penable,E_POINTER); CAutoLock foo(&m_SoundTouchLock); *penable = m_Enable; return NOERROR; } STDMETHODIMP CSoundTouch::put_Enable( bool enable ) { CAutoLock foo(&m_SoundTouchLock); m_Enable = enable; CPersistStream::SetDirty(TRUE); return NOERROR; } //GetPages STDMETHODIMP CSoundTouch::GetPages(CAUUID * pPages) { CheckPointer(pPages,E_POINTER); pPages->cElems = 1; pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID)); if (pPages->pElems == NULL) { return E_OUTOFMEMORY; } *(pPages->pElems) = CLSID_SoundTouchProp; return NOERROR; } //DLL STDAPI DllRegisterServer() { return AMovieDllRegisterServer2( TRUE ); } STDAPI DllUnregisterServer() { return AMovieDllRegisterServer2( FALSE ); } // // DllEntryPoint // extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID); BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved); }