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

Last change on this file since 7 was 7, checked in by roman, 11 years ago

sine wave generation

  • Property svn:keywords set to Id
File size: 19.4 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2011
3// Created by Roman Ryltsov roman@alax.info
4//
5// $Id: GeneratePcmWavFile.cpp 7 2011-08-26 08:20:52Z 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
151                public:
152                // COutputPin
153                        COutputPin() throw() :
154                                m_nDataLength(0),
155                                m_fSignalPeriod(0),
156                                m_fSignalAmplitude(0)
157                        {
158                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
159                        }
160                        ~COutputPin() throw()
161                        {
162                                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
163                        }
164                        VOID EnumerateMediaTypes(CAtlList<CMediaType>& MediaTypeList)
165                        {
166                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
167                                _W(MediaTypeList.AddTail(m_pDataMediaType));
168                        }
169                        BOOL CheckMediaType(const CMediaType& pMediaType) const throw()
170                        {
171                                _A(pMediaType);
172                                //if(pMediaType->majortype != MEDIATYPE_Audio || pMediaType->subtype != MEDIASUBTYPE_PCM)
173                                //      return FALSE;
174                                //const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
175                                //if(!pWaveFormatEx)
176                                //      return FALSE;
177                                return m_pDataMediaType.Compare(pMediaType);
178                        }
179                        BOOL DecideMemAllocatorProperties(IMemAllocator* pMemAllocator, ALLOCATOR_PROPERTIES Properties) throw()
180                        {
181                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
182                                const CMediaType& pMediaType = GetMediaTypeReference();
183                                const CWaveFormatEx* pWaveFormatEx = pMediaType.GetWaveFormatEx();
184                                if(!pWaveFormatEx)
185                                        return FALSE;
186                                if(!__super::DecideMemAllocatorProperties(pMemAllocator, Properties))
187                                        return FALSE;
188                                static const ULONG g_nDefaultBufferLength = 500; // 500 ms
189                                const SIZE_T nDefaultBufferBlockCount = (pWaveFormatEx->nAvgBytesPerSec * g_nDefaultBufferLength / 1000 + pWaveFormatEx->nBlockAlign - 1) / pWaveFormatEx->nBlockAlign;
190                                const SIZE_T nDefaultBufferSize = nDefaultBufferBlockCount * pWaveFormatEx->nBlockAlign;
191                                if(Properties.cbBuffer < (LONG) nDefaultBufferSize)
192                                        Properties.cbBuffer = (LONG) nDefaultBufferSize;
193                                if(Properties.cbAlign < pWaveFormatEx->nBlockAlign)
194                                        Properties.cbAlign = pWaveFormatEx->nBlockAlign;
195                                if(!SetMemAllocatorBufferSize(pMemAllocator, Properties))
196                                        return FALSE;
197                                const SIZE_T nSampleCount = Properties.cbBuffer / pWaveFormatEx->nBlockAlign;
198                                const SIZE_T nEffectiveBufferSize = nSampleCount * pWaveFormatEx->nBlockAlign;
199                                const REFERENCE_TIME nBufferTime = (REFERENCE_TIME) (1000 * 10000) * nEffectiveBufferSize / pWaveFormatEx->nAvgBytesPerSec;
200                                SetLatency(nBufferTime);
201                                return TRUE;
202                        }
203                        VOID InitializeThread(CThreadContext& ThreadContext) throw()
204                        {
205                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
206                                __super::InitializeThread(ThreadContext);
207                                if(m_fSignalPeriod > 0)
208                                {
209                                        __D(m_pDataMediaType.GetWaveFormatEx()->wBitsPerSample == 16, E_NOTIMPL);
210                                        ThreadContext.m_nCurrentSampleIndex = 0;
211                                }
212                        }
213                        BOOL ComposeMediaSample(CThreadContext& ThreadContext, IMediaSample* pMediaSample)
214                        {
215                                CMediaSampleProperties Properties(pMediaSample);
216                                _A(!Properties.pMediaType);
217                                if(ThreadContext.m_nMediaSampleTime >= m_nDataLength)
218                                        return FALSE; // Finished
219                                CRoCriticalSectionLock DataLock(GetDataCriticalSection());
220                                const CWaveFormatEx* pWaveFormatEx = GetMediaTypeReference().GetWaveFormatEx();
221                                _A(pWaveFormatEx);
222                                const SIZE_T nRemainedDataSize = (SIZE_T) ((m_nDataLength - ThreadContext.m_nMediaSampleTime) * pWaveFormatEx->nAvgBytesPerSec / (1000 * 10000i64));
223                                SIZE_T nDataSize = Properties.cbBuffer;
224                                if(nDataSize > nRemainedDataSize)
225                                        nDataSize = nRemainedDataSize;
226                                nDataSize = (nDataSize / pWaveFormatEx->nBlockAlign) * pWaveFormatEx->nBlockAlign;
227                                if(pWaveFormatEx->wBitsPerSample == 8)
228                                {
229                                        FillMemory(Properties.pbBuffer, nDataSize, 0x80);
230                                } else
231                                {
232                                        ZeroMemory(Properties.pbBuffer, nDataSize);
233                                        #pragma region Size Wave Data
234                                        if(m_fSignalPeriod > 0)
235                                        {
236#if _DEVELOPMENT
237                                                const SIZE_T nAnchorCurrentSampleIndex = ThreadContext.m_nCurrentSampleIndex;
238#endif // _DEVELOPMENT
239                                                for(SIZE_T nIndex = 0; nIndex < nDataSize; nIndex += pWaveFormatEx->nBlockAlign)
240                                                {
241                                                        const SHORT nValue = (SHORT) (m_fSignalAmplitude * sin(2 * M_PI * ThreadContext.m_nCurrentSampleIndex++ / m_fSignalPeriod));
242                                                        SHORT* pnSampleData = (SHORT*) (Properties.pbBuffer + nIndex);
243                                                        for(WORD nChannelIndex = 0; nChannelIndex < pWaveFormatEx->nChannels; nChannelIndex++)
244                                                                pnSampleData[nChannelIndex] = nValue;
245                                                }
246#if _DEVELOPMENT
247                                                _A(ThreadContext.m_nCurrentSampleIndex == nAnchorCurrentSampleIndex + nDataSize / pWaveFormatEx->nBlockAlign);
248#endif // _DEVELOPMENT
249                                        }
250                                        #pragma endregion
251                                }
252                                ThreadContext.m_nMediaSampleTime += nDataSize * (1000 * 10000i64) / pWaveFormatEx->nAvgBytesPerSec;
253                                //ThreadContext.m_nCurrentSampleIndex += nDataSize / pWaveFormatEx->nBlockAlign;
254                                Properties.lActual = (LONG) nDataSize;
255                                Properties.Set();
256                                return TRUE;
257                        }
258                        VOID InitializeData(const CWaveFormatEx* pWaveFormatEx, REFERENCE_TIME nLength)
259                        {
260                                _A(pWaveFormatEx);
261                                _A(nLength > 0);
262                                __D(!m_pDataMediaType, E_UNNAMED);
263                                m_pDataMediaType.AllocateWaveFormatEx(pWaveFormatEx);
264                                m_nDataLength = nLength;
265                        }
266                        VOID InitializeSignal(DOUBLE fSignalPeriod, DOUBLE fSignalAmplitude)
267                        {
268                                __D(fSignalPeriod > 0 && fSignalAmplitude >= 0, E_INVALIDARG);
269                                m_fSignalPeriod = fSignalPeriod;
270                                m_fSignalAmplitude = fSignalAmplitude;
271                        }
272                };
273
274        private:
275                CObjectPtr<COutputPin> m_pOutputPin;
276
277        public:
278        // CSourceFilter
279                CSourceFilter() throw() :
280                        CBasePersistT<CSourceFilter>(GetDataCriticalSection())
281                {
282                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
283                }
284                ~CSourceFilter() throw()
285                {
286                        _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
287                }
288                HRESULT FinalConstruct() throw()
289                {
290                        _ATLTRY
291                        {
292                                m_pOutputPin.Construct()->Initialize(this, L"Output");
293                                AddPin(m_pOutputPin);
294                        }
295                        _ATLCATCH(Exception)
296                        {
297                                _C(Exception);
298                        }
299                        return S_OK;
300                }
301                VOID FinalRelease() throw()
302                {
303                        m_pOutputPin = NULL;
304                }
305                VOID DeliverBeginFlush(IPin*)
306                {
307                        m_pOutputPin->DeliverBeginFlush();
308                }
309                VOID DeliverEndFlush(IPin*)
310                {
311                        m_pOutputPin->DeliverEndFlush();
312                }
313                VOID DeliverNewSegment(IPin*, REFERENCE_TIME nStartTime, REFERENCE_TIME nStopTime, DOUBLE fRate)
314                {
315                        m_pOutputPin->DeliverNewSegment(nStartTime, nStopTime, fRate);
316                }
317                static BOOL CanCue() throw()
318                {
319                        return FALSE;
320                }
321                VOID CueFilter()
322                {
323                        m_pOutputPin->CuePin();
324                }
325                VOID RunFilter(REFERENCE_TIME nStartTime)
326                {
327                        m_pOutputPin->RunPin(nStartTime);
328                }
329                VOID PauseFilter() throw()
330                {
331                        m_pOutputPin->PausePin();
332                }
333                VOID StopFilter() throw()
334                {
335                        m_pOutputPin->StopPin();
336                }
337                const CObjectPtr<COutputPin>& GetOutputPin() const throw()
338                {
339                        return m_pOutputPin;
340                }
341                VOID Initialize(const CWaveFormatEx* pWaveFormatEx, REFERENCE_TIME nLength)
342                {
343                        m_pOutputPin->InitializeData(pWaveFormatEx, nLength);
344                }
345                VOID InitializeSignal(DOUBLE fSignalAmplitude, DOUBLE fSignalPeriod)
346                {
347                        m_pOutputPin->InitializeSignal(fSignalAmplitude, fSignalPeriod);
348                }
349        };
350
351private:
352        CWaveFormatEx m_WaveFormatEx;
353        REFERENCE_TIME m_nLength;
354        UINT m_nSignalFrequency;
355        UINT m_nSignalLoudness;
356        CPath m_sPath;
357
358public:
359// CModule
360        CModule() throw()
361        {
362#if defined(_DEBUG)
363                AtlTraceLoadSettings(NULL);
364#endif // defined(_DEBUG)
365                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
366                ZeroMemory(&m_WaveFormatEx, sizeof m_WaveFormatEx);
367                m_nLength = 0;
368                m_nSignalFrequency = 0;
369                m_nSignalLoudness = 0;
370        }
371        ~CModule() throw()
372        {
373                _Z4(atlTraceRefcount, 4, _T("this 0x%p\n"), this);
374        }
375        VOID SetSampleRate(UINT nSampleRate)
376        {
377                __D(nSampleRate > 0, E_INVALIDARG);
378                m_WaveFormatEx.nSamplesPerSec = (DWORD) nSampleRate;
379        }
380        VOID SetChannelCount(UINT nChannelCount)
381        {
382                __D(nChannelCount > 0, E_INVALIDARG);
383                m_WaveFormatEx.nChannels = (WORD) nChannelCount;
384        }
385        VOID SetSampleBitCount(UINT nSampleBitCount)
386        {
387                __D(nSampleBitCount == 8 || nSampleBitCount == 16, E_INVALIDARG);
388                m_WaveFormatEx.wBitsPerSample = (WORD) nSampleBitCount;
389        }
390        VOID SetLength(REFERENCE_TIME nLength)
391        {
392                __D(nLength > 0, E_INVALIDARG);
393                m_nLength = nLength;
394        }
395        VOID SetSignalFrequency(UINT nSignalFrequency)
396        {
397                __D(nSignalFrequency > 0, E_INVALIDARG);
398                m_nSignalFrequency = nSignalFrequency;
399        }
400        VOID SetSignalLoudness(UINT nSignalLoudness)
401        {
402                __D(nSignalLoudness >= 0, E_INVALIDARG);
403                m_nSignalLoudness = nSignalLoudness;
404        }
405        VOID SetPath(LPCTSTR pszPath)
406        {
407                __D(_tcslen(pszPath), E_INVALIDARG);
408                __D(!_tcslen(m_sPath), E_INVALIDARG);
409                m_sPath = pszPath;
410        }
411        HRESULT PreMessageLoop(INT nShowCommand)
412        {
413                __C(__super::PreMessageLoop(nShowCommand));
414                return S_OK;
415        }
416        VOID RunMessageLoop()
417        {
418                #pragma region Input Validation and Syntax
419                if(!m_WaveFormatEx.nSamplesPerSec || !m_WaveFormatEx.nChannels || !m_WaveFormatEx.wBitsPerSample || !m_nLength || !_tcslen(m_sPath))
420                {
421                        _tprintf(_T("Syntax: GeneratePcmWavFile <options> <output-path>\n"));
422                        _tprintf(_T("  /s:N: Sampling Rate N, Hz\n"));
423                        _tprintf(_T("  /c:N: Channel Count N\n"));
424                        _tprintf(_T("  /b:N: Sample Bit Count N, 8 or 16\n"));
425                        _tprintf(_T("  /t:N: Length N, seconds\n"));
426                        _tprintf(_T("  /f:N: Sine Signal Frequency N, Hz\n"));
427                        _tprintf(_T("  /l:N: Sine Signal Loudness N, dB below full scale\n"));
428                        __C(S_FALSE);
429                }
430                #pragma endregion
431                #pragma region Complete Audio Format
432                m_WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
433                m_WaveFormatEx.nBlockAlign = m_WaveFormatEx.nChannels * ((m_WaveFormatEx.wBitsPerSample + 7) >> 3);
434                m_WaveFormatEx.nAvgBytesPerSec = m_WaveFormatEx.nSamplesPerSec * m_WaveFormatEx.nBlockAlign;
435                CWaveFormatEx* pWaveFormatEx = &m_WaveFormatEx;
436                // SUGG: Replace with WAVEFORMATEXTENSIBLE where appropriate
437                #pragma endregion
438                #pragma region Filter Graph
439                CGenericFilterGraph GenericFilterGraph(TRUE);
440                GenericFilterGraph.CoCreateInstance();
441                CObjectPtr<CSourceFilter> pSourceFilter;
442                pSourceFilter.Construct()->Initialize(pWaveFormatEx, m_nLength);
443                if(m_nSignalFrequency)
444                {
445                        __D(m_WaveFormatEx.wBitsPerSample == 16, E_NOTIMPL);
446                        const DOUBLE fSignalPeriod = (DOUBLE) pWaveFormatEx->nSamplesPerSec / m_nSignalFrequency;
447                        const DOUBLE fSignalAmplitude = 32767.0 / pow(10.0, m_nSignalLoudness / 20.0);
448                        pSourceFilter->InitializeSignal(fSignalPeriod, fSignalAmplitude);
449                }
450                __C(GenericFilterGraph->AddFilter(pSourceFilter, CT2CW(_T("Source"))));
451                CComPtr<IPin> pCurrentOutputPin = pSourceFilter->GetOutputPin();
452                #pragma region WAV Dest
453                CComPtr<IBaseFilter> pWavDestBaseFilter;
454                _ATLTRY
455                {
456                        __C(pWavDestBaseFilter.CoCreateInstance(_PersistHelper::ClassIdentifierFromString(CT2CW(_T("{3C78B8E2-6C4D-11D1-ADE2-0000F8754B99}")))));
457                        __C(GenericFilterGraph->AddFilter(pWavDestBaseFilter, CT2CW(_T(".WAV Multiplexer"))));
458                        __C(GenericFilterGraph->Connect(pCurrentOutputPin, _FilterGraphHelper::GetFilterPin(pWavDestBaseFilter, PINDIR_INPUT)));
459                        pCurrentOutputPin = _FilterGraphHelper::GetFilterPin(pWavDestBaseFilter, PINDIR_OUTPUT);
460                }
461                _ATLCATCH(Exception)
462                {
463                        _tprintf(_T("There was an error trying to instantiate WAV Dest filter, Exception 0x%08X\n"), (HRESULT) Exception);
464                        _ATLRETHROW;
465                }
466                #pragma endregion
467                #pragma region File Writer
468                CComPtr<IBaseFilter> pFileWriterBaseFilter;
469                __C(pFileWriterBaseFilter.CoCreateInstance(CLSID_FileWriter));
470                CComQIPtr<IFileSinkFilter2> pFileSinkFilter2 = pFileWriterBaseFilter;
471                __D(pFileSinkFilter2, E_NOINTERFACE);
472                _tprintf(_T("Writing into \"%s\"...\n"), m_sPath);
473                __C(pFileSinkFilter2->SetFileName(CT2CW(m_sPath), NULL));
474                __C(pFileSinkFilter2->SetMode(AM_FILE_OVERWRITE));
475                __C(GenericFilterGraph->AddFilter(pFileWriterBaseFilter, CT2CW(_T("File Writer"))));
476                __C(GenericFilterGraph->Connect(pCurrentOutputPin, _FilterGraphHelper::GetFilterPin(pFileWriterBaseFilter, PINDIR_INPUT)));
477                pCurrentOutputPin.Release();
478                #pragma endregion
479                _A(!pCurrentOutputPin);
480                _A(GenericFilterGraph.m_pMediaFilter);
481                __C(GenericFilterGraph.m_pMediaFilter->SetSyncSource(NULL));
482                #pragma endregion
483                _tprintf(_T("Running...\n"));
484                _A(GenericFilterGraph.m_pMediaControl);
485                __C(GenericFilterGraph.m_pMediaControl->Run());
486                GenericFilterGraph.SetShowDestructorMessageBox(FALSE);
487                _A(GenericFilterGraph.m_pMediaEventEx);
488                LONG nEventCode;
489                __C(GenericFilterGraph.m_pMediaEventEx->WaitForCompletion(INFINITE, &nEventCode));
490                _tprintf(_T("Complete, nEventCode 0x%02X\n"), nEventCode);
491                __C(GenericFilterGraph.m_pMediaControl->Stop());
492        }
493};
494
495////////////////////////////////////////////////////////////
496// Main
497
498int _tmain(int argc, _TCHAR* argv[])
499{
500        _ATLTRY
501        {
502                CModule Module;
503                #pragma region Parse Command Line
504                for(INT nIndex = 1; nIndex < argc; nIndex++)
505                {
506                        CString sArgument = argv[nIndex];
507                        _A(!sArgument.IsEmpty());
508                        #pragma region Switches
509                        if(_tcschr(_T("-/"), sArgument[0]))
510                        {
511                                sArgument.Delete(0);
512                                #pragma region Switch Value/Specification
513                                CString sArgumentValue;
514                                if(sArgument.GetLength() > 1)
515                                {
516                                        SIZE_T nIndex = 1;
517                                        if(sArgument[1] == _T(':'))
518                                                nIndex++;
519                                        sArgumentValue = (LPCTSTR) sArgument + nIndex;
520                                }
521                                INT nIntegerArgumentValue = 0;
522                                const BOOL bIntegerArgumentValueValid = !sArgumentValue.IsEmpty() ? AtlStringToInteger(sArgumentValue, nIntegerArgumentValue) : FALSE;
523                                #pragma endregion
524                                if(_tcschr(_T("Ss"), sArgument[0])) // Sample Rate
525                                {
526                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
527                                        //_tprintf(_T("Option: Sample Rate, %d\n"), nIntegerArgumentValue);
528                                        Module.SetSampleRate(nIntegerArgumentValue);
529                                } else
530                                if(_tcschr(_T("Cc"), sArgument[0])) // Channel Count
531                                {
532                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
533                                        //_tprintf(_T("Option: Channel Count, %d\n"), nIntegerArgumentValue);
534                                        Module.SetChannelCount(nIntegerArgumentValue);
535                                } else
536                                if(_tcschr(_T("Bb"), sArgument[0])) // Sample Bit Count
537                                {
538                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
539                                        //_tprintf(_T("Option: Sample Bit Count, %d\n"), nIntegerArgumentValue);
540                                        Module.SetSampleBitCount(nIntegerArgumentValue);
541                                } else
542                                if(_tcschr(_T("Tt"), sArgument[0])) // Length, seconds
543                                {
544                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
545                                        //_tprintf(_T("Option: Length, %d\n"), nIntegerArgumentValue);
546                                        Module.SetLength(nIntegerArgumentValue * 1000 * 10000i64);
547                                } else
548                                if(_tcschr(_T("Ff"), sArgument[0])) // Sine Signal Frequency, Hz
549                                {
550                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
551                                        //_tprintf(_T("Option: Sine Signal Frequency, %d\n"), nIntegerArgumentValue);
552                                        Module.SetSignalFrequency(nIntegerArgumentValue);
553                                } else
554                                if(_tcschr(_T("Ll"), sArgument[0])) // Sine Signal Loudness, dB below FS
555                                {
556                                        __D(bIntegerArgumentValueValid, E_INVALIDARG);
557                                        //_tprintf(_T("Option: Sine Signal Loudness, %d\n"), nIntegerArgumentValue);
558                                        Module.SetSignalLoudness(nIntegerArgumentValue);
559                                }
560                                continue;
561                        }
562                        #pragma endregion
563                        if(sArgument.GetLength() >= 2 && sArgument[0] == _T('"') && sArgument[sArgument.GetLength() - 1] == _T('"'))
564                                sArgument = sArgument.Mid(1, sArgument.GetLength() - 2);
565                        Module.SetPath(sArgument);
566                }
567                #pragma endregion
568                Module.WinMain(SW_SHOWNORMAL);
569        }
570        _ATLCATCH(Exception)
571        {
572                if(FAILED((HRESULT) Exception))
573                        _tprintf(_T("Error 0x%08x: %s\n"), (HRESULT) Exception, AtlFormatSystemMessage(Exception).TrimRight(_T("\t\n\r .")));
574                return (INT) (HRESULT) Exception;
575        }
576        _ATLCATCHALL()
577        {
578                _tprintf(_T("Fatal Error\n"));
579                return (INT) E_FAIL;
580        }
581        return 0;
582}
Note: See TracBrowser for help on using the repository browser.