source: trunk/Utilities/GeneratePcmWavFile/GeneratePcmWavFile.cpp @ 65

Last change on this file since 65 was 65, checked in by roman, 11 years ago
  • Property svn:keywords set to Id
File size: 22.6 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2011
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: GeneratePcmWavFile.cpp 65 2012-05-22 18:31:40Z roman $
6
7#include "stdafx.h"
8#include "rodshow.h"
9
10////////////////////////////////////////////////////////////
11// CModule
12
13class CModule : 
14        public CAtlExeModuleT<CModule>
15{
16        typedef CThreadT<CModule> CThread;
17
18public:
19
20        ////////////////////////////////////////////////////////
21        // CGenericFilterGraph
22
23        class CGenericFilterGraph
24        {
25        public:
26#if _DEVELOPMENT
27                BOOL m_bShowDestructorMessageBox;
28#endif // _DEVELOPMENT
29                CComPtr<IFilterGraph2> m_pFilterGraph;
30                CComPtr<IMediaControl> m_pMediaControl;
31                CComPtr<IMediaEventEx> m_pMediaEventEx;
32                CComPtr<IMediaFilter> m_pMediaFilter;
33                CComPtr<IMediaPosition> m_pMediaPosition;
34
35        public:
36        // CGenericFilterGraph
37                CGenericFilterGraph(BOOL bShowDestructorMessageBox = FALSE) throw()
38                {
39                        bShowDestructorMessageBox;
40#if _DEVELOPMENT
41                        m_bShowDestructorMessageBox = bShowDestructorMessageBox;
42#endif // _DEVELOPMENT
43                }
44                ~CGenericFilterGraph() throw()
45                {
46#if _DEVELOPMENT
47                        if(m_pFilterGraph && m_bShowDestructorMessageBox)
48                                AtlMessageBox(GetActiveWindow(), _T("DirectShow Filter Graph is about to be Released - Break In"), _T("Debug"), MB_ICONWARNING | MB_OK);
49#endif // _DEVELOPMENT
50                }
51                VOID CoCreateInstance(const CLSID& ClassIdentifier = CLSID_FilterGraph)
52                {
53                        __C(m_pFilterGraph.CoCreateInstance(ClassIdentifier));
54                        m_pMediaControl = CComQIPtr<IMediaControl>(m_pFilterGraph);
55                        m_pMediaEventEx = CComQIPtr<IMediaEventEx>(m_pFilterGraph);
56                        m_pMediaFilter = CComQIPtr<IMediaFilter>(m_pFilterGraph);
57                        m_pMediaPosition = CComQIPtr<IMediaPosition>(m_pFilterGraph);
58                        __D(m_pMediaControl && m_pMediaEventEx && m_pMediaFilter && m_pMediaPosition, E_NOINTERFACE);
59                }
60                VOID SetShowDestructorMessageBox(BOOL bShowDestructorMessageBox = TRUE)
61                {
62                        bShowDestructorMessageBox;
63#if _DEVELOPMENT
64                        m_bShowDestructorMessageBox = bShowDestructorMessageBox;
65#endif // _DEVELOPMENT
66                }
67                operator const CComPtr<IFilterGraph2>& () const throw()
68                {
69                        return m_pFilterGraph;
70                }
71                const CComPtr<IFilterGraph2>& operator -> () const throw()
72                {
73                        return m_pFilterGraph;
74                }
75        };
76
77        ////////////////////////////////////////////////////////
78        // CSourceFilter
79
80        class ATL_NO_VTABLE CSourceFilter :
81                public CComObjectRootEx<CComMultiThreadModelNoCS>,
82                public CComCoClass<CSourceFilter>,
83                public CPushSourceFilterT<CSourceFilter>,
84                public CBasePersistT<CSourceFilter>,
85                public CAmFilterMiscFlagsT<CSourceFilter, AM_FILTER_MISC_FLAGS_IS_SOURCE>
86        {
87        public:
88
89        DECLARE_NO_REGISTRY()
90
91        DECLARE_PROTECT_FINAL_CONSTRUCT()
92
93        //DECLARE_QI_TRACE(CSourceFilter)
94
95        BEGIN_COM_MAP(CSourceFilter)
96                COM_INTERFACE_ENTRY(IBaseFilter)
97                COM_INTERFACE_ENTRY(IMediaFilter)
98                COM_INTERFACE_ENTRY_IID(__uuidof(IPersist), IBaseFilter)
99                COM_INTERFACE_ENTRY(IAMFilterMiscFlags)
100        END_COM_MAP()
101
102        public:
103
104                ////////////////////////////////////////////////////////
105                // CThreadContext
106
107                class COutputPin;
108
109                class CThreadContext :
110                        public CPushSourceFilterT<CSourceFilter>::CThreadContext
111                {
112                public:
113                        CEvent m_MediaSampleTimeEvent;
114                        REFERENCE_TIME m_nMediaSampleTime;
115                        SIZE_T m_nCurrentSampleIndex;
116
117                public:
118                // CThreadContext
119                        CThreadContext(CEvent& TerminationEvent) throw() :
120                                CPushSourceFilter::CThreadContext(TerminationEvent),
121                                m_nMediaSampleTime(0),
122                                m_nCurrentSampleIndex(0)
123                        {
124                        }
125                };
126
127                ////////////////////////////////////////////////////////
128                // COutputPin
129
130                class ATL_NO_VTABLE COutputPin :
131                        public CComObjectRootEx<CComMultiThreadModelNoCS>,
132                        public CPushSourceFilterT<CSourceFilter>::COutputPinT<COutputPin, CSourceFilter, CThreadContext>,
133                        public CAmPushSourceT<COutputPin, 0>
134                {
135                public:
136
137                //DECLARE_QI_TRACE(CSourceFilter::COutputPin)
138
139                BEGIN_COM_MAP(COutputPin)
140                        COM_INTERFACE_ENTRY(IPin)
141                        COM_INTERFACE_ENTRY(IAMPushSource)
142                        COM_INTERFACE_ENTRY(IAMLatency)
143                END_COM_MAP()
144
145                public:
146                        CMediaType m_pDataMediaType;
147                        REFERENCE_TIME m_nDataLength;
148                        DOUBLE m_fSignalPeriod;
149                        DOUBLE m_fSignalAmplitude;
150                        DOUBLE m_fNoiseAmplitude;
151
152                public:
153                // COutputPin
154                        COutputPin() throw() :
155                                m_nDataLength(0),
156                                m_fSignalPeriod(0),
157                                m_fSignalAmplitude(0),
158                                m_fNoiseAmplitude(0)
159                        {
160                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
161                        }
162                        ~COutputPin() throw()
163                        {
164                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
165                        }
166                        VOID EnumerateMediaTypes(CAtlList<CMediaType>& MediaTypeList)
167                        {
168                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
169                                _W(MediaTypeList.AddTail(m_pDataMediaType));
170                        }
171                        BOOL CheckMediaType(const CMediaType& pMediaType) const throw()
172                        {
173                                _A(pMediaType);
174                                //if(pMediaType->majortype != MEDIATYPE_Audio || pMediaType->subtype != MEDIASUBTYPE_PCM)
175                                //      return FALSE;
176                                //const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
177                                //if(!pWaveFormatEx)
178                                //      return FALSE;
179                                return m_pDataMediaType.Compare(pMediaType);
180                        }
181                        BOOL DecideMemAllocatorProperties(IMemAllocator* pMemAllocator, ALLOCATOR_PROPERTIES Properties) throw()
182                        {
183                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
184                                const CMediaType& pMediaType = GetMediaTypeReference();
185                                const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
186                                if(!pWaveFormatEx)
187                                        return FALSE;
188                                if(!__super::DecideMemAllocatorProperties(pMemAllocator, Properties))
189                                        return FALSE;
190                                static const ULONG g_nDefaultBufferLength = 500; // 500 ms
191                                const SIZE_T nDefaultBufferBlockCount = (pWaveFormatEx->nAvgBytesPerSec * g_nDefaultBufferLength / 1000 + pWaveFormatEx->nBlockAlign - 1) / pWaveFormatEx->nBlockAlign;
192                                const SIZE_T nDefaultBufferSize = nDefaultBufferBlockCount * pWaveFormatEx->nBlockAlign;
193                                if(Properties.cbBuffer < (LONG) nDefaultBufferSize)
194                                        Properties.cbBuffer = (LONG) nDefaultBufferSize;
195                                if(Properties.cbAlign < pWaveFormatEx->nBlockAlign)
196                                        Properties.cbAlign = pWaveFormatEx->nBlockAlign;
197                                if(!SetMemAllocatorBufferSize(pMemAllocator, Properties))
198                                        return FALSE;
199                                const SIZE_T nSampleCount = Properties.cbBuffer / pWaveFormatEx->nBlockAlign;
200                                const SIZE_T nEffectiveBufferSize = nSampleCount * pWaveFormatEx->nBlockAlign;
201                                const REFERENCE_TIME nBufferTime = (REFERENCE_TIME) (1000 * 10000) * nEffectiveBufferSize / pWaveFormatEx->nAvgBytesPerSec;
202                                SetLatency(nBufferTime);
203                                return TRUE;
204                        }
205                        VOID InitializeThread(CThreadContext& ThreadContext) throw()
206                        {
207                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
208                                __super::InitializeThread(ThreadContext);
209                                if(m_fSignalPeriod > 0)
210                                {
211                                        __D(m_pDataMediaType.GetWaveFormatEx()->wBitsPerSample == 16, E_NOTIMPL);
212                                        ThreadContext.m_nCurrentSampleIndex = 0;
213                                }
214                        }
215                        BOOL ComposeMediaSample(CThreadContext& ThreadContext, IMediaSample* pMediaSample)
216                        {
217                                CMediaSampleProperties Properties(pMediaSample);
218                                _A(!Properties.pMediaType);
219                                if(ThreadContext.m_nMediaSampleTime >= m_nDataLength)
220                                        return FALSE; // Finished
221                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
222                                const CWaveFormatEx* pWaveFormatEx = GetMediaTypeReference().GetWaveFormatEx();
223                                _A(pWaveFormatEx);
224                                const SIZE_T nRemainedDataSize = (SIZE_T) ((m_nDataLength - ThreadContext.m_nMediaSampleTime) * pWaveFormatEx->nAvgBytesPerSec / (1000 * 10000i64));
225                                SIZE_T nDataSize = Properties.cbBuffer;
226                                if(nDataSize > nRemainedDataSize)
227                                        nDataSize = nRemainedDataSize;
228                                nDataSize = (nDataSize / pWaveFormatEx->nBlockAlign) * pWaveFormatEx->nBlockAlign;
229                                if(pWaveFormatEx->wBitsPerSample == 8)
230                                {
231                                        FillMemory(Properties.pbBuffer, nDataSize, 0x80);
232                                } else
233                                {
234                                        ZeroMemory(Properties.pbBuffer, nDataSize);
235                                        #pragma region Sine Wave Data
236                                        if(m_fSignalPeriod > 0)
237                                        {
238                                                SIZE_T nSampleIndex = 0;
239                                                for(SIZE_T nIndex = 0; nIndex < nDataSize; nIndex += pWaveFormatEx->nBlockAlign, nSampleIndex++)
240                                                {
241                                                        #pragma region Per-channel Frequencies and Amplitudes
242                                                        if(FALSE)
243                                                        {
244                                                                const DOUBLE pfSignalFrequencies[5] = { 1000, 1000, 1000, 1000, 1000 };
245                                                                const DOUBLE pfSignalAmplitudes[5] = { m_fSignalAmplitude, 0, 0, 0, 0 };
246                                                                SHORT* pnSampleData = (SHORT*) (Properties.pbBuffer + nIndex);
247                                                                for(WORD nChannelIndex = 0; nChannelIndex < pWaveFormatEx->nChannels; nChannelIndex++)
248                                                                {
249                                                                        const DOUBLE fSignalPeriod = (DOUBLE) pWaveFormatEx->nSamplesPerSec / pfSignalFrequencies[nChannelIndex];
250                                                                        const DOUBLE fSignalAmplitude = pfSignalAmplitudes[nChannelIndex];
251                                                                        const SHORT nValue = (SHORT) (fSignalAmplitude * sin(2 * M_PI * (ThreadContext.m_nCurrentSampleIndex + nSampleIndex) / fSignalPeriod));
252                                                                        pnSampleData[nChannelIndex] = nValue;
253                                                                }
254                                                                continue;
255                                                        }
256                                                        #pragma endregion
257                                                        #pragma region Stream Time Coefficients
258                                                        #if TRUE && FALSE
259                                                        {
260                                                                COMPILER_MESSAGE("Every 170 seconds: 50 seconds 1.0, 70 seconds 0.0, 50 seconds 1.0");
261                                                                #pragma region Factor
262                                                                REFERENCE_TIME nTime = ThreadContext.m_nMediaSampleTime + nIndex * (1000 * 10000i64) / pWaveFormatEx->nAvgBytesPerSec;
263                                                                nTime /= 1000 * 10000i64;
264                                                                // NOTE: Every 170 seconds: 50 seconds 1.0, 70 seconds 0.0, 50 seconds 1.0
265                                                                nTime %= 170;
266                                                                const DOUBLE fTimeFactor = (nTime < 50 || nTime >= 120) ? 1.0 : (1.0 / 256);
267                                                                #pragma endregion
268                                                                const SHORT nValue = (SHORT) (m_fSignalAmplitude * sin(2 * M_PI * (ThreadContext.m_nCurrentSampleIndex + nSampleIndex) / m_fSignalPeriod));
269                                                                SHORT* pnSampleData = (SHORT*) (Properties.pbBuffer + nIndex);
270                                                                for(WORD nChannelIndex = 0; nChannelIndex < pWaveFormatEx->nChannels; nChannelIndex++)
271                                                                        pnSampleData[nChannelIndex] = (SHORT) (fTimeFactor * nValue);
272                                                                continue;
273                                                        }
274                                                        #endif // TRUE
275                                                        #pragma endregion
276                                                        const SHORT nValue = (SHORT) (m_fSignalAmplitude * sin(2 * M_PI * (ThreadContext.m_nCurrentSampleIndex + nSampleIndex) / m_fSignalPeriod));
277                                                        SHORT* pnSampleData = (SHORT*) (Properties.pbBuffer + nIndex);
278                                                        for(WORD nChannelIndex = 0; nChannelIndex < pWaveFormatEx->nChannels; nChannelIndex++)
279                                                                pnSampleData[nChannelIndex] = nValue;
280                                                }
281                                        }
282                                        #pragma endregion
283                                        #pragma region Noise Wave Data
284                                        if(m_fNoiseAmplitude > 0)
285                                        {
286                                                for(SIZE_T nIndex = 0; nIndex < nDataSize; nIndex += pWaveFormatEx->nBlockAlign)
287                                                {
288                                                        SHORT* pnSampleData = (SHORT*) (Properties.pbBuffer + nIndex);
289                                                        for(WORD nChannelIndex = 0; nChannelIndex < pWaveFormatEx->nChannels; nChannelIndex++)
290                                                                pnSampleData[nChannelIndex] += (SHORT) (m_fNoiseAmplitude * (DOUBLE) (rand() - RAND_MAX / 2) / (RAND_MAX / 2));
291                                                }
292                                        }
293                                        #pragma endregion
294                                }
295                                ThreadContext.m_nMediaSampleTime += nDataSize * (1000 * 10000i64) / pWaveFormatEx->nAvgBytesPerSec;
296                                ThreadContext.m_nCurrentSampleIndex += nDataSize / pWaveFormatEx->nBlockAlign;
297                                Properties.lActual = (LONG) nDataSize;
298                                Properties.Set();
299                                return TRUE;
300                        }
301                        VOID InitializeData(const CWaveFormatEx* pWaveFormatEx, REFERENCE_TIME nLength)
302                        {
303                                _A(pWaveFormatEx);
304                                _A(nLength > 0);
305                                __D(!m_pDataMediaType, E_UNNAMED);
306                                m_pDataMediaType.AllocateWaveFormatEx(pWaveFormatEx);
307                                m_nDataLength = nLength;
308                        }
309                        VOID InitializeSignal(DOUBLE fSignalPeriod, DOUBLE fSignalAmplitude, DOUBLE fNoiseAmplitude)
310                        {
311                                __D(fSignalPeriod >= 0 && fSignalAmplitude >= 0 && fNoiseAmplitude >= 0, E_INVALIDARG);
312                                m_fSignalPeriod = fSignalPeriod;
313                                m_fSignalAmplitude = fSignalAmplitude;
314                                m_fNoiseAmplitude = fNoiseAmplitude;
315                        }
316                };
317
318        private:
319                CObjectPtr<COutputPin> m_pOutputPin;
320
321        public:
322        // CSourceFilter
323                CSourceFilter() throw() :
324                        CBasePersistT<CSourceFilter>(GetDataCriticalSection())
325                {
326                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
327                }
328                ~CSourceFilter() throw()
329                {
330                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
331                }
332                HRESULT FinalConstruct() throw()
333                {
334                        _ATLTRY
335                        {
336                                m_pOutputPin.Construct()->Initialize(this, L"Output");
337                                AddPin(m_pOutputPin);
338                        }
339                        _ATLCATCH(Exception)
340                        {
341                                _C(Exception);
342                        }
343                        return S_OK;
344                }
345                VOID FinalRelease() throw()
346                {
347                        m_pOutputPin = NULL;
348                }
349                VOID DeliverBeginFlush(IPin*)
350                {
351                        m_pOutputPin->DeliverBeginFlush();
352                }
353                VOID DeliverEndFlush(IPin*)
354                {
355                        m_pOutputPin->DeliverEndFlush();
356                }
357                VOID DeliverNewSegment(IPin*, REFERENCE_TIME nStartTime, REFERENCE_TIME nStopTime, DOUBLE fRate)
358                {
359                        m_pOutputPin->DeliverNewSegment(nStartTime, nStopTime, fRate);
360                }
361                static BOOL CanCue() throw()
362                {
363                        return FALSE;
364                }
365                VOID CueFilter()
366                {
367                        m_pOutputPin->CuePin();
368                }
369                VOID RunFilter(REFERENCE_TIME nStartTime)
370                {
371                        m_pOutputPin->RunPin(nStartTime);
372                }
373                VOID PauseFilter() throw()
374                {
375                        m_pOutputPin->PausePin();
376                }
377                VOID StopFilter() throw()
378                {
379                        m_pOutputPin->StopPin();
380                }
381                const CObjectPtr<COutputPin>& GetOutputPin() const throw()
382                {
383                        return m_pOutputPin;
384                }
385                VOID Initialize(const CWaveFormatEx* pWaveFormatEx, REFERENCE_TIME nLength)
386                {
387                        m_pOutputPin->InitializeData(pWaveFormatEx, nLength);
388                }
389                VOID InitializeSignal(DOUBLE fSignalAmplitude, DOUBLE fSignalPeriod, DOUBLE fNoiseAmplitude)
390                {
391                        m_pOutputPin->InitializeSignal(fSignalAmplitude, fSignalPeriod, fNoiseAmplitude);
392                }
393        };
394
395private:
396        CWaveFormatEx m_WaveFormatEx;
397        REFERENCE_TIME m_nLength;
398        UINT m_nSignalFrequency;
399        UINT m_nSignalLoudness;
400        UINT m_nNoiseLoudness;
401        CPath m_sPath;
402
403public:
404// CModule
405        CModule() throw()
406        {
407#if defined(_DEBUG)
408                AtlTraceLoadSettings(NULL);
409#endif // defined(_DEBUG)
410                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
411                ZeroMemory(&m_WaveFormatEx, sizeof m_WaveFormatEx);
412                m_nLength = 0;
413                m_nSignalFrequency = 0;
414                m_nSignalLoudness = 0;
415                m_nNoiseLoudness = 0;
416        }
417        ~CModule() throw()
418        {
419                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
420        }
421        VOID SetSampleRate(UINT nSampleRate)
422        {
423                __D(nSampleRate > 0, E_INVALIDARG);
424                m_WaveFormatEx.nSamplesPerSec = (DWORD) nSampleRate;
425        }
426        VOID SetChannelCount(UINT nChannelCount)
427        {
428                __D(nChannelCount > 0, E_INVALIDARG);
429                m_WaveFormatEx.nChannels = (WORD) nChannelCount;
430        }
431        VOID SetSampleBitCount(UINT nSampleBitCount)
432        {
433                __D(nSampleBitCount == 8 || nSampleBitCount == 16, E_INVALIDARG);
434                m_WaveFormatEx.wBitsPerSample = (WORD) nSampleBitCount;
435        }
436        VOID SetLength(REFERENCE_TIME nLength)
437        {
438                __D(nLength > 0, E_INVALIDARG);
439                m_nLength = nLength;
440        }
441        VOID SetSignalFrequency(UINT nSignalFrequency)
442        {
443                __D(nSignalFrequency > 0, E_INVALIDARG);
444                m_nSignalFrequency = nSignalFrequency;
445        }
446        VOID SetSignalLoudness(UINT nSignalLoudness)
447        {
448                __D(nSignalLoudness >= 0, E_INVALIDARG);
449                m_nSignalLoudness = nSignalLoudness;
450        }
451        VOID SetNoiseLoudness(UINT nNoiseLoudness)
452        {
453                __D(nNoiseLoudness >= 0, E_INVALIDARG);
454                m_nNoiseLoudness = nNoiseLoudness;
455        }
456        VOID SetPath(LPCTSTR pszPath)
457        {
458                __D(_tcslen(pszPath), E_INVALIDARG);
459                __D(!_tcslen(m_sPath), E_INVALIDARG);
460                m_sPath = pszPath;
461        }
462        HRESULT PreMessageLoop(INT nShowCommand)
463        {
464                __C(__super::PreMessageLoop(nShowCommand));
465                return S_OK;
466        }
467        VOID RunMessageLoop()
468        {
469                #pragma region Input Validation and Syntax
470                if(!m_WaveFormatEx.nSamplesPerSec || !m_WaveFormatEx.nChannels || !m_WaveFormatEx.wBitsPerSample || !m_nLength || !_tcslen(m_sPath))
471                {
472                        _tprintf(_T("Syntax: GeneratePcmWavFile <options> <output-path>\n"));
473                        _tprintf(_T("  /s:N: Sampling Rate N, Hz\n"));
474                        _tprintf(_T("  /c:N: Channel Count N\n"));
475                        _tprintf(_T("  /b:N: Sample Bit Count N, 8 or 16\n"));
476                        _tprintf(_T("  /t:N: Length N, seconds\n"));
477                        _tprintf(_T("  /f:N: Sine Signal Frequency N, Hz\n"));
478                        _tprintf(_T("  /l:N: Sine Signal Loudness N, dB below full scale\n"));
479                        _tprintf(_T("  /n:N: Noise Signal Loudness N, dB below full scale\n"));
480                        AtlThrow(S_FALSE);
481                }
482                #pragma endregion
483                #pragma region Complete Audio Format
484                m_WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
485                m_WaveFormatEx.nBlockAlign = m_WaveFormatEx.nChannels * ((m_WaveFormatEx.wBitsPerSample + 7) >> 3);
486                m_WaveFormatEx.nAvgBytesPerSec = m_WaveFormatEx.nSamplesPerSec * m_WaveFormatEx.nBlockAlign;
487                CWaveFormatEx* pWaveFormatEx = &m_WaveFormatEx;
488                // SUGG: Replace with WAVEFORMATEXTENSIBLE where appropriate
489                #pragma endregion
490                #pragma region Filter Graph
491                CGenericFilterGraph GenericFilterGraph(TRUE);
492                GenericFilterGraph.CoCreateInstance();
493                CObjectPtr<CSourceFilter> pSourceFilter;
494                pSourceFilter.Construct()->Initialize(pWaveFormatEx, m_nLength);
495                if(m_nSignalFrequency && m_nSignalLoudness >= 0 || m_nNoiseLoudness)
496                {
497                        __D(m_WaveFormatEx.wBitsPerSample == 16, E_NOTIMPL);
498                        DOUBLE fSignalPeriod = 0, fSignalAmplitude = 0;
499                        if(m_nSignalFrequency && m_nSignalLoudness >= 0)
500                        {
501                                fSignalPeriod = (DOUBLE) pWaveFormatEx->nSamplesPerSec / m_nSignalFrequency;
502                                fSignalAmplitude = 32767.0 / pow(10.0, m_nSignalLoudness / 20.0);
503                        }
504                        DOUBLE fNoiseAmplitude = 0;
505                        if(m_nNoiseLoudness)
506                        {
507                                fNoiseAmplitude = 32767.0 / pow(10.0, m_nNoiseLoudness / 20.0);
508                        }
509                        pSourceFilter->InitializeSignal(fSignalPeriod, fSignalAmplitude, fNoiseAmplitude);
510                }
511                __C(GenericFilterGraph->AddFilter(pSourceFilter, CT2CW(_T("Source"))));
512                CComPtr<IPin> pCurrentOutputPin = pSourceFilter->GetOutputPin();
513                #pragma region WAV Dest
514                CComPtr<IBaseFilter> pWavDestBaseFilter;
515                _ATLTRY
516                {
517                        __C(pWavDestBaseFilter.CoCreateInstance(_PersistHelper::ClassIdentifierFromString(CT2CW(_T("{3C78B8E2-6C4D-11D1-ADE2-0000F8754B99}")))));
518                        __C(GenericFilterGraph->AddFilter(pWavDestBaseFilter, CT2CW(_T(".WAV Multiplexer"))));
519                        __C(GenericFilterGraph->Connect(pCurrentOutputPin, _FilterGraphHelper::GetFilterPin(pWavDestBaseFilter, PINDIR_INPUT)));
520                        pCurrentOutputPin = _FilterGraphHelper::GetFilterPin(pWavDestBaseFilter, PINDIR_OUTPUT);
521                }
522                _ATLCATCH(Exception)
523                {
524                        _tprintf(_T("There was an error trying to instantiate WAV Dest filter, Exception 0x%08X\n"), (HRESULT) Exception);
525                        _ATLRETHROW;
526                }
527                #pragma endregion
528                #pragma region File Writer
529                CComPtr<IBaseFilter> pFileWriterBaseFilter;
530                __C(pFileWriterBaseFilter.CoCreateInstance(CLSID_FileWriter));
531                CComQIPtr<IFileSinkFilter2> pFileSinkFilter2 = pFileWriterBaseFilter;
532                __D(pFileSinkFilter2, E_NOINTERFACE);
533                _tprintf(_T("Writing into \"%s\"...\n"), m_sPath);
534                __C(pFileSinkFilter2->SetFileName(CT2CW(m_sPath), NULL));
535                __C(pFileSinkFilter2->SetMode(AM_FILE_OVERWRITE));
536                __C(GenericFilterGraph->AddFilter(pFileWriterBaseFilter, CT2CW(_T("File Writer"))));
537                __C(GenericFilterGraph->Connect(pCurrentOutputPin, _FilterGraphHelper::GetFilterPin(pFileWriterBaseFilter, PINDIR_INPUT)));
538                pCurrentOutputPin.Release();
539                #pragma endregion
540                _A(!pCurrentOutputPin);
541                _A(GenericFilterGraph.m_pMediaFilter);
542                __C(GenericFilterGraph.m_pMediaFilter->SetSyncSource(NULL));
543                #pragma endregion
544                _tprintf(_T("Running...\n"));
545                _A(GenericFilterGraph.m_pMediaControl);
546                __C(GenericFilterGraph.m_pMediaControl->Run());
547                GenericFilterGraph.SetShowDestructorMessageBox(FALSE);
548                _A(GenericFilterGraph.m_pMediaEventEx);
549                LONG nEventCode;
550                __C(GenericFilterGraph.m_pMediaEventEx->WaitForCompletion(INFINITE, &nEventCode));
551                _tprintf(_T("Complete, nEventCode 0x%02X\n"), nEventCode);
552                __C(GenericFilterGraph.m_pMediaControl->Stop());
553        }
554};
555
556////////////////////////////////////////////////////////////
557// Main
558
559int _tmain(int argc, _TCHAR* argv[])
560{
561        _ATLTRY
562        {
563                CModule Module;
564                #pragma region Parse Command Line
565                for(INT nIndex = 1; nIndex < argc; nIndex++)
566                {
567                        CString sArgument = argv[nIndex];
568                        _A(!sArgument.IsEmpty());
569                        #pragma region Switches
570                        if(_tcschr(_T("-/"), sArgument[0]))
571                        {
572                                sArgument.Delete(0);
573                                #pragma region Switch Value/Specification
574                                CString sArgumentValue;
575                                if(sArgument.GetLength() > 1)
576                                {
577                                        SIZE_T nIndex = 1;
578                                        if(sArgument[1] == _T(':'))
579                                                nIndex++;
580                                        sArgumentValue = (LPCTSTR) sArgument + nIndex;
581                                }
582                                INT nIntegerArgumentValue = 0;
583                                const BOOL bIntegerArgumentValueValid = !sArgumentValue.IsEmpty() ? AtlStringToInteger(sArgumentValue, nIntegerArgumentValue) : FALSE;
584                                #pragma endregion
585                                if(_tcschr(_T("Ss"), sArgument[0])) // Sample Rate
586                                {
587                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
588                                        //_tprintf(_T("Option: Sample Rate, %d\n"), nIntegerArgumentValue);
589                                        Module.SetSampleRate(nIntegerArgumentValue);
590                                } else
591                                if(_tcschr(_T("Cc"), sArgument[0])) // Channel Count
592                                {
593                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
594                                        //_tprintf(_T("Option: Channel Count, %d\n"), nIntegerArgumentValue);
595                                        Module.SetChannelCount(nIntegerArgumentValue);
596                                } else
597                                if(_tcschr(_T("Bb"), sArgument[0])) // Sample Bit Count
598                                {
599                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
600                                        //_tprintf(_T("Option: Sample Bit Count, %d\n"), nIntegerArgumentValue);
601                                        Module.SetSampleBitCount(nIntegerArgumentValue);
602                                } else
603                                if(_tcschr(_T("Tt"), sArgument[0])) // Length, seconds
604                                {
605                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
606                                        //_tprintf(_T("Option: Length, %d\n"), nIntegerArgumentValue);
607                                        Module.SetLength(nIntegerArgumentValue * 1000 * 10000i64);
608                                } else
609                                if(_tcschr(_T("Ff"), sArgument[0])) // Sine Signal Frequency, Hz
610                                {
611                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
612                                        //_tprintf(_T("Option: Sine Signal Frequency, %d\n"), nIntegerArgumentValue);
613                                        Module.SetSignalFrequency(nIntegerArgumentValue);
614                                } else
615                                if(_tcschr(_T("Ll"), sArgument[0])) // Sine Signal Loudness, dB below FS
616                                {
617                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
618                                        //_tprintf(_T("Option: Sine Signal Loudness, %d\n"), nIntegerArgumentValue);
619                                        Module.SetSignalLoudness(nIntegerArgumentValue);
620                                } else
621                                if(_tcschr(_T("Nn"), sArgument[0])) // Noise Signal Loudness, dB below FS
622                                {
623                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
624                                        //_tprintf(_T("Option: Noise Signal Loudness, %d\n"), nIntegerArgumentValue);
625                                        Module.SetNoiseLoudness(nIntegerArgumentValue);
626                                }
627                                continue;
628                        }
629                        #pragma endregion
630                        if(sArgument.GetLength() >= 2 && sArgument[0] == _T('"') && sArgument[sArgument.GetLength() - 1] == _T('"'))
631                                sArgument = sArgument.Mid(1, sArgument.GetLength() - 2);
632                        Module.SetPath(sArgument);
633                }
634                #pragma endregion
635                Module.WinMain(SW_SHOWNORMAL);
636        }
637        _ATLCATCH(Exception)
638        {
639                if(FAILED((HRESULT) Exception))
640                        _tprintf(_T("Error 0x%08x: %s\n"), (HRESULT) Exception, AtlFormatSystemMessage(Exception).TrimRight(_T("\t\n\r .")));
641                return (INT) (HRESULT) Exception;
642        }
643        _ATLCATCHALL()
644        {
645                _tprintf(_T("Fatal Error\n"));
646                return (INT) E_FAIL;
647        }
648        return 0;
649}
Note: See TracBrowser for help on using the repository browser.