1159b3361Sopenharmony_ci/**
2159b3361Sopenharmony_ci *
3159b3361Sopenharmony_ci * Lame ACM wrapper, encode/decode MP3 based RIFF/AVI files in MS Windows
4159b3361Sopenharmony_ci *
5159b3361Sopenharmony_ci *  Copyright (c) 2002 Steve Lhomme <steve.lhomme at free.fr>
6159b3361Sopenharmony_ci *
7159b3361Sopenharmony_ci * This library is free software; you can redistribute it and/or
8159b3361Sopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9159b3361Sopenharmony_ci * License as published by the Free Software Foundation; either
10159b3361Sopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11159b3361Sopenharmony_ci *
12159b3361Sopenharmony_ci * This library is distributed in the hope that it will be useful,
13159b3361Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14159b3361Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15159b3361Sopenharmony_ci * Lesser General Public License for more details.
16159b3361Sopenharmony_ci *
17159b3361Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18159b3361Sopenharmony_ci * License along with this library; if not, write to the Free Software
19159b3361Sopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20159b3361Sopenharmony_ci *
21159b3361Sopenharmony_ci */
22159b3361Sopenharmony_ci
23159b3361Sopenharmony_ci/*!
24159b3361Sopenharmony_ci	\author Steve Lhomme
25159b3361Sopenharmony_ci	\version \$Id$
26159b3361Sopenharmony_ci*/
27159b3361Sopenharmony_ci
28159b3361Sopenharmony_ci#if !defined(STRICT)
29159b3361Sopenharmony_ci#define STRICT
30159b3361Sopenharmony_ci#endif // STRICT
31159b3361Sopenharmony_ci
32159b3361Sopenharmony_ci#include <algorithm>
33159b3361Sopenharmony_ci
34159b3361Sopenharmony_ci#include <windows.h>
35159b3361Sopenharmony_ci#include <windowsx.h>
36159b3361Sopenharmony_ci#include <intshcut.h>
37159b3361Sopenharmony_ci
38159b3361Sopenharmony_ci#include <mmreg.h>
39159b3361Sopenharmony_ci#include <msacm.h>
40159b3361Sopenharmony_ci#include <msacmdrv.h>
41159b3361Sopenharmony_ci
42159b3361Sopenharmony_ci#include <assert.h>
43159b3361Sopenharmony_ci
44159b3361Sopenharmony_ci#include <lame.h>
45159b3361Sopenharmony_ci
46159b3361Sopenharmony_ci#include "adebug.h"
47159b3361Sopenharmony_ci#include "resource.h"
48159b3361Sopenharmony_ci#include "ACMStream.h"
49159b3361Sopenharmony_ci
50159b3361Sopenharmony_ci#ifdef ENABLE_DECODING
51159b3361Sopenharmony_ci#include "DecodeStream.h"
52159b3361Sopenharmony_ci#endif // ENABLE_DECODING
53159b3361Sopenharmony_ci
54159b3361Sopenharmony_ci#include "ACM.h"
55159b3361Sopenharmony_ci
56159b3361Sopenharmony_ci#ifndef IDC_HAND
57159b3361Sopenharmony_ci#define IDC_HAND            MAKEINTRESOURCE(32649)
58159b3361Sopenharmony_ci#endif // IDC_HAND
59159b3361Sopenharmony_ci
60159b3361Sopenharmony_cichar ACM::VersionString[120];
61159b3361Sopenharmony_ci
62159b3361Sopenharmony_ciconst char ACM_VERSION[] = "0.9.2";
63159b3361Sopenharmony_ci
64159b3361Sopenharmony_ci#ifdef WIN32
65159b3361Sopenharmony_ci//
66159b3361Sopenharmony_ci//  32-bit versions
67159b3361Sopenharmony_ci//
68159b3361Sopenharmony_ci#if (WINVER >= 0x0400)
69159b3361Sopenharmony_ci #define VERSION_ACM_DRIVER  MAKE_ACM_VERSION(4,  0, 0)
70159b3361Sopenharmony_ci#else
71159b3361Sopenharmony_ci#define VERSION_ACM_DRIVER  MAKE_ACM_VERSION(3, 51, 0)
72159b3361Sopenharmony_ci#endif
73159b3361Sopenharmony_ci#define VERSION_MSACM MAKE_ACM_VERSION(3, 50, 0)
74159b3361Sopenharmony_ci
75159b3361Sopenharmony_ci#else
76159b3361Sopenharmony_ci//
77159b3361Sopenharmony_ci//  16-bit versions
78159b3361Sopenharmony_ci//
79159b3361Sopenharmony_ci#define VERSION_ACM_DRIVER MAKE_ACM_VERSION(1, 0, 0)
80159b3361Sopenharmony_ci#define VERSION_MSACM MAKE_ACM_VERSION(2, 1, 0)
81159b3361Sopenharmony_ci
82159b3361Sopenharmony_ci#endif
83159b3361Sopenharmony_ci
84159b3361Sopenharmony_ci#define PERSONAL_FORMAT WAVE_FORMAT_MPEGLAYER3
85159b3361Sopenharmony_ci#define SIZE_FORMAT_STRUCT sizeof(MPEGLAYER3WAVEFORMAT)
86159b3361Sopenharmony_ci//#define SIZE_FORMAT_STRUCT 0
87159b3361Sopenharmony_ci
88159b3361Sopenharmony_ci//static const char channel_mode[][13] = {"mono","stereo","joint stereo","dual channel"};
89159b3361Sopenharmony_cistatic const char channel_mode[][13] = {"mono","stereo"};
90159b3361Sopenharmony_cistatic const unsigned int mpeg1_freq[] = {48000,44100,32000};
91159b3361Sopenharmony_cistatic const unsigned int mpeg2_freq[] = {24000,22050,16000,12000,11025,8000};
92159b3361Sopenharmony_cistatic const unsigned int mpeg1_bitrate[] = {320, 256, 224, 192, 160, 128, 112, 96, 80, 64, 56, 48, 40, 32};
93159b3361Sopenharmony_cistatic const unsigned int mpeg2_bitrate[] = {160, 144, 128, 112,  96,  80,  64, 56, 48, 40, 32, 24, 16,  8};
94159b3361Sopenharmony_ci
95159b3361Sopenharmony_ci#define SIZE_CHANNEL_MODE (sizeof(channel_mode)  / (sizeof(char) * 13))
96159b3361Sopenharmony_ci#define SIZE_FREQ_MPEG1 (sizeof(mpeg1_freq)    / sizeof(unsigned int))
97159b3361Sopenharmony_ci#define SIZE_FREQ_MPEG2 (sizeof(mpeg2_freq)    / sizeof(unsigned int))
98159b3361Sopenharmony_ci#define SIZE_BITRATE_MPEG1 (sizeof(mpeg1_bitrate) / sizeof(unsigned int))
99159b3361Sopenharmony_ci#define SIZE_BITRATE_MPEG2 (sizeof(mpeg2_bitrate) / sizeof(unsigned int))
100159b3361Sopenharmony_ci
101159b3361Sopenharmony_cistatic const int FORMAT_TAG_MAX_NB = 2; // PCM and PERSONAL (mandatory to have at least PCM and your format)
102159b3361Sopenharmony_cistatic const int FILTER_TAG_MAX_NB = 0; // this is a codec, not a filter
103159b3361Sopenharmony_ci
104159b3361Sopenharmony_ci// number of supported PCM formats
105159b3361Sopenharmony_cistatic const int FORMAT_MAX_NB_PCM =
106159b3361Sopenharmony_ci	2 *                                           // number of PCM channel mode (stereo/mono)
107159b3361Sopenharmony_ci		(SIZE_FREQ_MPEG1 + // number of MPEG 1 sampling freq
108159b3361Sopenharmony_ci		SIZE_FREQ_MPEG2); // number of MPEG 2 sampling freq
109159b3361Sopenharmony_ci
110159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
111159b3361Sopenharmony_ci//
112159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
113159b3361Sopenharmony_cibool bitrate_item::operator<(const bitrate_item & other_bitrate) const
114159b3361Sopenharmony_ci{
115159b3361Sopenharmony_ci	return (other_bitrate.frequency < frequency ||
116159b3361Sopenharmony_ci		    (other_bitrate.frequency == frequency &&
117159b3361Sopenharmony_ci			 (other_bitrate.bitrate < bitrate ||
118159b3361Sopenharmony_ci			  (other_bitrate.bitrate == bitrate &&
119159b3361Sopenharmony_ci			   (other_bitrate.channels < channels)))));
120159b3361Sopenharmony_ci}
121159b3361Sopenharmony_ci
122159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
123159b3361Sopenharmony_ci// Configuration Dialog
124159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
125159b3361Sopenharmony_ci/*
126159b3361Sopenharmony_cistatic CALLBACK ConfigProc(
127159b3361Sopenharmony_ci  HWND hwndDlg,  // handle to dialog box
128159b3361Sopenharmony_ciUINT uMsg,     // message
129159b3361Sopenharmony_ciWPARAM wParam, // first message parameter
130159b3361Sopenharmony_ciLPARAM lParam  // second message parameter
131159b3361Sopenharmony_ci)
132159b3361Sopenharmony_ci{
133159b3361Sopenharmony_ci	BOOL bResult;
134159b3361Sopenharmony_ci
135159b3361Sopenharmony_ci	switch (uMsg) {
136159b3361Sopenharmony_ci		case WM_COMMAND:
137159b3361Sopenharmony_ci			UINT command;
138159b3361Sopenharmony_ci			command = GET_WM_COMMAND_ID(wParam, lParam);
139159b3361Sopenharmony_ci            if (IDOK == command)
140159b3361Sopenharmony_ci            {
141159b3361Sopenharmony_ci                EndDialog(hwndDlg, (IDOK == command));
142159b3361Sopenharmony_ci            } else if (IDCANCEL == command)
143159b3361Sopenharmony_ci            {
144159b3361Sopenharmony_ci                EndDialog(hwndDlg, (IDOK == command));
145159b3361Sopenharmony_ci            }
146159b3361Sopenharmony_ci            bResult = FALSE;
147159b3361Sopenharmony_ci			break;
148159b3361Sopenharmony_ci		default:
149159b3361Sopenharmony_ci			bResult = FALSE; // will be treated by DefWindowProc
150159b3361Sopenharmony_ci}
151159b3361Sopenharmony_ci	return bResult;
152159b3361Sopenharmony_ci}
153159b3361Sopenharmony_ci
154159b3361Sopenharmony_ci
155159b3361Sopenharmony_ciinline DWORD ACM::Configure(HWND hParentWindow, LPDRVCONFIGINFO pConfig)
156159b3361Sopenharmony_ci{
157159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "ACM : Configure (Parent Window = 0x%08X)",hParentWindow);
158159b3361Sopenharmony_ci
159159b3361Sopenharmony_ci	DialogBoxParam( my_hModule, MAKEINTRESOURCE(IDD_CONFIG), hParentWindow, ::ConfigProc , (LPARAM)this);
160159b3361Sopenharmony_ci
161159b3361Sopenharmony_ci	return DRVCNF_OK; // Can also return
162159b3361Sopenharmony_ci					// DRVCNF_CANCEL
163159b3361Sopenharmony_ci					// and DRVCNF_RESTART
164159b3361Sopenharmony_ci}
165159b3361Sopenharmony_ci*/
166159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
167159b3361Sopenharmony_ci// About Dialog
168159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
169159b3361Sopenharmony_ci
170159b3361Sopenharmony_cistatic BOOL CALLBACK AboutProc(
171159b3361Sopenharmony_ci  HWND hwndDlg,  // handle to dialog box
172159b3361Sopenharmony_ciUINT uMsg,     // message
173159b3361Sopenharmony_ciWPARAM wParam, // first message parameter
174159b3361Sopenharmony_ciLPARAM lParam  // second message parameter
175159b3361Sopenharmony_ci)
176159b3361Sopenharmony_ci{
177159b3361Sopenharmony_ci	static HBRUSH hBrushStatic = NULL;
178159b3361Sopenharmony_ci//	static LOGFONT lf;  // structure for font information
179159b3361Sopenharmony_ci//	static HFONT hfnt;
180159b3361Sopenharmony_ci	static HCURSOR hcOverCursor = NULL;
181159b3361Sopenharmony_ci	BOOL bResult = FALSE;
182159b3361Sopenharmony_ci
183159b3361Sopenharmony_ci	switch (uMsg) {
184159b3361Sopenharmony_ci		case WM_INITDIALOG:
185159b3361Sopenharmony_ci			char tmp[150];
186159b3361Sopenharmony_ci			wsprintf(tmp,"LAME MP3 codec v%s", ACM::GetVersionString());
187159b3361Sopenharmony_ci			::SetWindowText(GetDlgItem( hwndDlg, IDC_STATIC_ABOUT_TITLE), tmp);
188159b3361Sopenharmony_ci
189159b3361Sopenharmony_ci/*
190159b3361Sopenharmony_ci			::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
191159b3361Sopenharmony_ci			lf.lfUnderline = TRUE;
192159b3361Sopenharmony_ci
193159b3361Sopenharmony_ci			hfnt = ::CreateFontIndirect(&lf);
194159b3361Sopenharmony_ci
195159b3361Sopenharmony_ci			::SendMessage(::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL), WM_SETFONT, (WPARAM) hfnt, TRUE);
196159b3361Sopenharmony_ci* /
197159b3361Sopenharmony_ci			hBrushStatic = ::CreateSolidBrush(::GetSysColor (COLOR_BTNFACE));
198159b3361Sopenharmony_ci*/			hcOverCursor = ::LoadCursor(NULL,(LPCTSTR)IDC_HAND);
199159b3361Sopenharmony_ci			if (hcOverCursor == NULL)
200159b3361Sopenharmony_ci				hcOverCursor = ::LoadCursor(NULL,(LPCTSTR)IDC_CROSS);
201159b3361Sopenharmony_ci
202159b3361Sopenharmony_ci			bResult = TRUE;
203159b3361Sopenharmony_ci			break;
204159b3361Sopenharmony_ci/*
205159b3361Sopenharmony_ci		case WM_CTLCOLORSTATIC:
206159b3361Sopenharmony_ci			/// \todo only if there are URLs
207159b3361Sopenharmony_ci			if ((HWND)lParam == ::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL))
208159b3361Sopenharmony_ci			{
209159b3361Sopenharmony_ci				::SetTextColor((HDC)wParam, ::GetSysColor (COLOR_HIGHLIGHT));
210159b3361Sopenharmony_ci				::SetBkColor((HDC)wParam, ::GetSysColor (COLOR_BTNFACE));
211159b3361Sopenharmony_ci
212159b3361Sopenharmony_ci				return (LRESULT) hBrushStatic;
213159b3361Sopenharmony_ci			}
214159b3361Sopenharmony_ci			else
215159b3361Sopenharmony_ci				return (LRESULT) NULL;
216159b3361Sopenharmony_ci*/
217159b3361Sopenharmony_ci		case WM_MOUSEMOVE:
218159b3361Sopenharmony_ci			{
219159b3361Sopenharmony_ci				POINT pnt;
220159b3361Sopenharmony_ci				::GetCursorPos(&pnt);
221159b3361Sopenharmony_ci
222159b3361Sopenharmony_ci				RECT rect;
223159b3361Sopenharmony_ci				::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL), &rect);
224159b3361Sopenharmony_ci
225159b3361Sopenharmony_ci				if (  ::PtInRect(&rect,pnt)  )
226159b3361Sopenharmony_ci				{
227159b3361Sopenharmony_ci					::SetCursor(hcOverCursor);
228159b3361Sopenharmony_ci				}
229159b3361Sopenharmony_ci
230159b3361Sopenharmony_ci
231159b3361Sopenharmony_ci			}
232159b3361Sopenharmony_ci			break;
233159b3361Sopenharmony_ci
234159b3361Sopenharmony_ci		case WM_LBUTTONUP:
235159b3361Sopenharmony_ci			{
236159b3361Sopenharmony_ci				POINT pnt;
237159b3361Sopenharmony_ci				::GetCursorPos(&pnt);
238159b3361Sopenharmony_ci
239159b3361Sopenharmony_ci				RECT rect;
240159b3361Sopenharmony_ci				::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL), &rect);
241159b3361Sopenharmony_ci
242159b3361Sopenharmony_ci				TCHAR Url[200];
243159b3361Sopenharmony_ci				bool bUrl = false;
244159b3361Sopenharmony_ci				if (::PtInRect(&rect,pnt))
245159b3361Sopenharmony_ci				{
246159b3361Sopenharmony_ci					wsprintf(Url,get_lame_url());
247159b3361Sopenharmony_ci					bUrl = true;
248159b3361Sopenharmony_ci				}
249159b3361Sopenharmony_ci
250159b3361Sopenharmony_ci				if (bUrl)
251159b3361Sopenharmony_ci				{
252159b3361Sopenharmony_ci					::ShellExecute(hwndDlg,"open",Url,NULL,"",SW_SHOWMAXIMIZED );
253159b3361Sopenharmony_ci				}
254159b3361Sopenharmony_ci
255159b3361Sopenharmony_ci			}
256159b3361Sopenharmony_ci			break;
257159b3361Sopenharmony_ci
258159b3361Sopenharmony_ci		case WM_COMMAND:
259159b3361Sopenharmony_ci			UINT command;
260159b3361Sopenharmony_ci			command = GET_WM_COMMAND_ID(wParam, lParam);
261159b3361Sopenharmony_ci            if (IDOK == command)
262159b3361Sopenharmony_ci            {
263159b3361Sopenharmony_ci                EndDialog(hwndDlg, TRUE);
264159b3361Sopenharmony_ci            }
265159b3361Sopenharmony_ci            bResult = FALSE;
266159b3361Sopenharmony_ci			break;
267159b3361Sopenharmony_ci
268159b3361Sopenharmony_ci		case IDC_STATIC_ABOUT_URL:
269159b3361Sopenharmony_ci			break;
270159b3361Sopenharmony_ci		default:
271159b3361Sopenharmony_ci			bResult = FALSE; // will be treated by DefWindowProc
272159b3361Sopenharmony_ci}
273159b3361Sopenharmony_ci	return bResult;
274159b3361Sopenharmony_ci}
275159b3361Sopenharmony_ci
276159b3361Sopenharmony_ciinline DWORD ACM::About(HWND hParentWindow)
277159b3361Sopenharmony_ci{
278159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "ACM : About (Parent Window = 0x%08X)",hParentWindow);
279159b3361Sopenharmony_ci
280159b3361Sopenharmony_ci	DialogBoxParam( my_hModule, MAKEINTRESOURCE(IDD_ABOUT), hParentWindow, ::AboutProc , (LPARAM)this);
281159b3361Sopenharmony_ci
282159b3361Sopenharmony_ci	return DRVCNF_OK; // Can also return
283159b3361Sopenharmony_ci// DRVCNF_CANCEL
284159b3361Sopenharmony_ci// and DRVCNF_RESTART
285159b3361Sopenharmony_ci}
286159b3361Sopenharmony_ci
287159b3361Sopenharmony_ci
288159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
289159b3361Sopenharmony_ci// Construction/Destruction
290159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
291159b3361Sopenharmony_ci
292159b3361Sopenharmony_ciACM::ACM( HMODULE hModule )
293159b3361Sopenharmony_ci :my_hModule(hModule),
294159b3361Sopenharmony_ci  my_hIcon(NULL),
295159b3361Sopenharmony_ci  my_debug(ADbg(DEBUG_LEVEL_CREATION)),
296159b3361Sopenharmony_ci  my_EncodingProperties(hModule)
297159b3361Sopenharmony_ci{
298159b3361Sopenharmony_ci	my_EncodingProperties.ParamsRestore();
299159b3361Sopenharmony_ci
300159b3361Sopenharmony_ci	/// \todo get the debug level from the registry
301159b3361Sopenharmony_ci	unsigned char DebugFileName[512];
302159b3361Sopenharmony_ci
303159b3361Sopenharmony_ci	char tmp[128];
304159b3361Sopenharmony_ci	wsprintf(tmp,"LAMEacm 0x%08X",this);
305159b3361Sopenharmony_ci	my_debug.setPrefix(tmp); /// \todo get it from the registry
306159b3361Sopenharmony_ci	my_debug.setIncludeTime(true);  /// \todo get it from the registry
307159b3361Sopenharmony_ci
308159b3361Sopenharmony_ci	// Check in the registry if we have to Output Debug information
309159b3361Sopenharmony_ci	DebugFileName[0] = '\0';
310159b3361Sopenharmony_ci
311159b3361Sopenharmony_ci	HKEY OssKey;
312159b3361Sopenharmony_ci	if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\MUKOLI", 0, KEY_READ , &OssKey ) == ERROR_SUCCESS) {
313159b3361Sopenharmony_ci		DWORD DataType;
314159b3361Sopenharmony_ci		DWORD DebugFileNameSize = 512;
315159b3361Sopenharmony_ci		if (RegQueryValueEx( OssKey, "DebugFile", NULL, &DataType, DebugFileName, &DebugFileNameSize ) == ERROR_SUCCESS) {
316159b3361Sopenharmony_ci			if (DataType == REG_SZ) {
317159b3361Sopenharmony_ci				my_debug.setUseFile(true);
318159b3361Sopenharmony_ci				my_debug.setDebugFile((char *)DebugFileName);
319159b3361Sopenharmony_ci				my_debug.OutPut("Debug file is %s",(char *)DebugFileName);
320159b3361Sopenharmony_ci			}
321159b3361Sopenharmony_ci		}
322159b3361Sopenharmony_ci	}
323159b3361Sopenharmony_ci        wsprintf(VersionString,"%s - %s", ACM_VERSION, get_lame_version() );
324159b3361Sopenharmony_ci	BuildBitrateTable();
325159b3361Sopenharmony_ci
326159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "New ACM Creation (0x%08X)",this);
327159b3361Sopenharmony_ci}
328159b3361Sopenharmony_ci
329159b3361Sopenharmony_ciACM::~ACM()
330159b3361Sopenharmony_ci{
331159b3361Sopenharmony_ci// not used, it's done automatically when closing the driver	if (my_hIcon != NULL)
332159b3361Sopenharmony_ci//		CloseHandle(my_hIcon);
333159b3361Sopenharmony_ci
334159b3361Sopenharmony_ci	bitrate_table.clear();
335159b3361Sopenharmony_ci
336159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "ACM Deleted (0x%08X)",this);
337159b3361Sopenharmony_ci}
338159b3361Sopenharmony_ci
339159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
340159b3361Sopenharmony_ci// Main message handler
341159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
342159b3361Sopenharmony_ci
343159b3361Sopenharmony_ciLONG ACM::DriverProcedure(const HDRVR hdrvr, const UINT msg, LONG lParam1, LONG lParam2)
344159b3361Sopenharmony_ci{
345159b3361Sopenharmony_ci    DWORD dwRes = 0L;
346159b3361Sopenharmony_ci
347159b3361Sopenharmony_ci//my_debug.OutPut(DEBUG_LEVEL_MSG, "message 0x%08X for ThisACM 0x%08X", msg, this);
348159b3361Sopenharmony_ci
349159b3361Sopenharmony_ciswitch (msg) {
350159b3361Sopenharmony_ci    case DRV_INSTALL:
351159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_INSTALL");
352159b3361Sopenharmony_ci		// Sent when the driver is installed.
353159b3361Sopenharmony_ci		dwRes = DRVCNF_OK;  // Can also return
354159b3361Sopenharmony_ci		break;              // DRVCNF_CANCEL
355159b3361Sopenharmony_ci							// and DRV_RESTART
356159b3361Sopenharmony_ci
357159b3361Sopenharmony_ci	case DRV_REMOVE:
358159b3361Sopenharmony_ci		// Sent when the driver is removed.
359159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_REMOVE");
360159b3361Sopenharmony_ci		dwRes = 1L;  // return value ignored
361159b3361Sopenharmony_ci		break;
362159b3361Sopenharmony_ci
363159b3361Sopenharmony_ci    case DRV_QUERYCONFIGURE:
364159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_QUERYCONFIGURE");
365159b3361Sopenharmony_ci		// Sent to determine if the driver can be
366159b3361Sopenharmony_ci		// configured.
367159b3361Sopenharmony_ci		dwRes = 1L;  // Zero indicates configuration
368159b3361Sopenharmony_ci		break;       // NOT supported
369159b3361Sopenharmony_ci
370159b3361Sopenharmony_ci	case DRV_CONFIGURE:
371159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_CONFIGURE");
372159b3361Sopenharmony_ci		// Sent to display the configuration
373159b3361Sopenharmony_ci		// dialog box for the driver.
374159b3361Sopenharmony_ci//		dwRes = Configure( (HWND) lParam1, (LPDRVCONFIGINFO) lParam2 );
375159b3361Sopenharmony_ci		if (my_EncodingProperties.Config(my_hModule, (HWND) lParam1))
376159b3361Sopenharmony_ci		{
377159b3361Sopenharmony_ci			dwRes = DRVCNF_OK; // Can also return
378159b3361Sopenharmony_ci					// DRVCNF_CANCEL
379159b3361Sopenharmony_ci					// and DRVCNF_RESTART
380159b3361Sopenharmony_ci		} else {
381159b3361Sopenharmony_ci			dwRes = DRVCNF_CANCEL;
382159b3361Sopenharmony_ci		}
383159b3361Sopenharmony_ci		break;
384159b3361Sopenharmony_ci
385159b3361Sopenharmony_ci	/**************************************
386159b3361Sopenharmony_ci	// ACM additional messages
387159b3361Sopenharmony_ci	***************************************/
388159b3361Sopenharmony_ci
389159b3361Sopenharmony_ci	case ACMDM_DRIVER_ABOUT:
390159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_DRIVER_ABOUT");
391159b3361Sopenharmony_ci
392159b3361Sopenharmony_ci		dwRes = About( (HWND) lParam1 );
393159b3361Sopenharmony_ci
394159b3361Sopenharmony_ci        break;
395159b3361Sopenharmony_ci
396159b3361Sopenharmony_ci	case ACMDM_DRIVER_DETAILS: // acmDriverDetails
397159b3361Sopenharmony_ci		// Fill-in general informations about the driver/codec
398159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_DRIVER_DETAILS");
399159b3361Sopenharmony_ci
400159b3361Sopenharmony_ci		dwRes = OnDriverDetails(hdrvr, (LPACMDRIVERDETAILS) lParam1);
401159b3361Sopenharmony_ci
402159b3361Sopenharmony_ci		break;
403159b3361Sopenharmony_ci
404159b3361Sopenharmony_ci	case ACMDM_FORMATTAG_DETAILS: // acmFormatTagDetails
405159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_FORMATTAG_DETAILS");
406159b3361Sopenharmony_ci
407159b3361Sopenharmony_ci		dwRes = OnFormatTagDetails((LPACMFORMATTAGDETAILS) lParam1, lParam2);
408159b3361Sopenharmony_ci
409159b3361Sopenharmony_ci        break;
410159b3361Sopenharmony_ci
411159b3361Sopenharmony_ci	case ACMDM_FORMAT_DETAILS: // acmFormatDetails
412159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_FORMAT_DETAILS");
413159b3361Sopenharmony_ci
414159b3361Sopenharmony_ci		dwRes = OnFormatDetails((LPACMFORMATDETAILS) lParam1, lParam2);
415159b3361Sopenharmony_ci
416159b3361Sopenharmony_ci        break;
417159b3361Sopenharmony_ci
418159b3361Sopenharmony_ci    case ACMDM_FORMAT_SUGGEST: // acmFormatSuggest
419159b3361Sopenharmony_ci		// Sent to determine if the driver can be
420159b3361Sopenharmony_ci		// configured.
421159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_FORMAT_SUGGEST");
422159b3361Sopenharmony_ci		dwRes = OnFormatSuggest((LPACMDRVFORMATSUGGEST) lParam1);
423159b3361Sopenharmony_ci        break;
424159b3361Sopenharmony_ci
425159b3361Sopenharmony_ci	/**************************************
426159b3361Sopenharmony_ci	// ACM stream messages
427159b3361Sopenharmony_ci	***************************************/
428159b3361Sopenharmony_ci
429159b3361Sopenharmony_ci	case ACMDM_STREAM_OPEN:
430159b3361Sopenharmony_ci	// Sent to determine if the driver can be
431159b3361Sopenharmony_ci	// configured.
432159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_OPEN");
433159b3361Sopenharmony_ci		dwRes = OnStreamOpen((LPACMDRVSTREAMINSTANCE) lParam1);
434159b3361Sopenharmony_ci        break;
435159b3361Sopenharmony_ci
436159b3361Sopenharmony_ci	case ACMDM_STREAM_SIZE:
437159b3361Sopenharmony_ci	// returns a recommended size for a source
438159b3361Sopenharmony_ci	// or destination buffer on an ACM stream
439159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_SIZE");
440159b3361Sopenharmony_ci		dwRes = OnStreamSize((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMSIZE)lParam2);
441159b3361Sopenharmony_ci        break;
442159b3361Sopenharmony_ci
443159b3361Sopenharmony_ci	case ACMDM_STREAM_PREPARE:
444159b3361Sopenharmony_ci	// prepares an ACMSTREAMHEADER structure for
445159b3361Sopenharmony_ci	// an ACM stream conversion
446159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_PREPARE");
447159b3361Sopenharmony_ci		dwRes = OnStreamPrepareHeader((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMSTREAMHEADER) lParam2);
448159b3361Sopenharmony_ci        break;
449159b3361Sopenharmony_ci
450159b3361Sopenharmony_ci	case ACMDM_STREAM_UNPREPARE:
451159b3361Sopenharmony_ci	// cleans up the preparation performed by
452159b3361Sopenharmony_ci	// the ACMDM_STREAM_PREPARE message for an ACM stream
453159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_UNPREPARE");
454159b3361Sopenharmony_ci		dwRes = OnStreamUnPrepareHeader((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMSTREAMHEADER) lParam2);
455159b3361Sopenharmony_ci        break;
456159b3361Sopenharmony_ci
457159b3361Sopenharmony_ci	case ACMDM_STREAM_CONVERT:
458159b3361Sopenharmony_ci	// perform a conversion on the specified conversion stream
459159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_CONVERT");
460159b3361Sopenharmony_ci		dwRes = OnStreamConvert((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMHEADER) lParam2);
461159b3361Sopenharmony_ci
462159b3361Sopenharmony_ci        break;
463159b3361Sopenharmony_ci
464159b3361Sopenharmony_ci	case ACMDM_STREAM_CLOSE:
465159b3361Sopenharmony_ci	// closes an ACM conversion stream
466159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_CLOSE");
467159b3361Sopenharmony_ci		dwRes = OnStreamClose((LPACMDRVSTREAMINSTANCE)lParam1);
468159b3361Sopenharmony_ci        break;
469159b3361Sopenharmony_ci
470159b3361Sopenharmony_ci	/**************************************
471159b3361Sopenharmony_ci	// Unknown message
472159b3361Sopenharmony_ci	***************************************/
473159b3361Sopenharmony_ci
474159b3361Sopenharmony_ci	default:
475159b3361Sopenharmony_ci	// Process any other messages.
476159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_MSG, "ACM::DriverProc unknown message (0x%08X), lParam1 = 0x%08X, lParam2 = 0x%08X", msg, lParam1, lParam2);
477159b3361Sopenharmony_ci		return DefDriverProc ((DWORD)this, hdrvr, msg, lParam1, lParam2);
478159b3361Sopenharmony_ci    }
479159b3361Sopenharmony_ci
480159b3361Sopenharmony_ci    return dwRes;
481159b3361Sopenharmony_ci}
482159b3361Sopenharmony_ci
483159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
484159b3361Sopenharmony_ci// Special message handlers
485159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////
486159b3361Sopenharmony_ci/*!
487159b3361Sopenharmony_ci	Retreive the config details of this ACM driver
488159b3361Sopenharmony_ci	The index represent the specified format
489159b3361Sopenharmony_ci
490159b3361Sopenharmony_ci	\param a_FormatDetails will be filled with all the corresponding data
491159b3361Sopenharmony_ci*/
492159b3361Sopenharmony_ciinline DWORD ACM::OnFormatDetails(LPACMFORMATDETAILS a_FormatDetails, const LPARAM a_Query)
493159b3361Sopenharmony_ci{
494159b3361Sopenharmony_ci	DWORD Result = ACMERR_NOTPOSSIBLE;
495159b3361Sopenharmony_ci
496159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATDETAILS a_Query = 0x%08X",a_Query);
497159b3361Sopenharmony_ci	switch (a_Query & ACM_FORMATDETAILSF_QUERYMASK) {
498159b3361Sopenharmony_ci
499159b3361Sopenharmony_ci		// Fill-in the informations corresponding to the FormatDetails->dwFormatTagIndex
500159b3361Sopenharmony_ci		case ACM_FORMATDETAILSF_INDEX :
501159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "enter ACM_FORMATDETAILSF_INDEX for index 0x%04X:%03d",a_FormatDetails->dwFormatTag,a_FormatDetails->dwFormatIndex);
502159b3361Sopenharmony_ci			if (a_FormatDetails->dwFormatTag == PERSONAL_FORMAT) {
503159b3361Sopenharmony_ci				if (a_FormatDetails->dwFormatIndex < GetNumberEncodingFormats()) {
504159b3361Sopenharmony_ci					LPWAVEFORMATEX WaveExt;
505159b3361Sopenharmony_ci					WaveExt = a_FormatDetails->pwfx;
506159b3361Sopenharmony_ci
507159b3361Sopenharmony_ci					WaveExt->wFormatTag = PERSONAL_FORMAT;
508159b3361Sopenharmony_ci
509159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format in  : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
510159b3361Sopenharmony_ci					GetMP3FormatForIndex(a_FormatDetails->dwFormatIndex, *WaveExt, a_FormatDetails->szFormat);
511159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format out : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
512159b3361Sopenharmony_ci					Result = MMSYSERR_NOERROR;
513159b3361Sopenharmony_ci				}
514159b3361Sopenharmony_ci				else
515159b3361Sopenharmony_ci				{
516159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATDETAILSF_INDEX unknown index 0x%04X:%03d",a_FormatDetails->dwFormatTag,a_FormatDetails->dwFormatIndex);
517159b3361Sopenharmony_ci				}
518159b3361Sopenharmony_ci			}
519159b3361Sopenharmony_ci			else if (a_FormatDetails->dwFormatTag == WAVE_FORMAT_PCM) {
520159b3361Sopenharmony_ci				if (a_FormatDetails->dwFormatIndex < FORMAT_MAX_NB_PCM) {
521159b3361Sopenharmony_ci					LPWAVEFORMATEX WaveExt;
522159b3361Sopenharmony_ci					WaveExt = a_FormatDetails->pwfx;
523159b3361Sopenharmony_ci
524159b3361Sopenharmony_ci					WaveExt->wFormatTag = WAVE_FORMAT_PCM;
525159b3361Sopenharmony_ci
526159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format in  : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
527159b3361Sopenharmony_ci					GetPCMFormatForIndex(a_FormatDetails->dwFormatIndex, *WaveExt, a_FormatDetails->szFormat);
528159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format out : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
529159b3361Sopenharmony_ci					Result = MMSYSERR_NOERROR;
530159b3361Sopenharmony_ci				}
531159b3361Sopenharmony_ci				else
532159b3361Sopenharmony_ci				{
533159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATDETAILSF_INDEX unknown index 0x%04X:%03d",a_FormatDetails->dwFormatTag,a_FormatDetails->dwFormatIndex);
534159b3361Sopenharmony_ci				}
535159b3361Sopenharmony_ci			}
536159b3361Sopenharmony_ci			else
537159b3361Sopenharmony_ci			{
538159b3361Sopenharmony_ci				my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Unknown a_FormatDetails->dwFormatTag = 0x%08X",a_FormatDetails->dwFormatTag);
539159b3361Sopenharmony_ci			}
540159b3361Sopenharmony_ci
541159b3361Sopenharmony_ci		case ACM_FORMATDETAILSF_FORMAT :
542159b3361Sopenharmony_ci			/// \todo we may output the corresponding strong (only for personal format)
543159b3361Sopenharmony_ci			LPWAVEFORMATEX WaveExt;
544159b3361Sopenharmony_ci			WaveExt = a_FormatDetails->pwfx;
545159b3361Sopenharmony_ci
546159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "enter ACM_FORMATDETAILSF_FORMAT : 0x%04X:%03d, format in : channels %d, sample rate %d",a_FormatDetails->dwFormatTag,a_FormatDetails->dwFormatIndex, WaveExt->nChannels, WaveExt->nSamplesPerSec);
547159b3361Sopenharmony_ci
548159b3361Sopenharmony_ci			Result = MMSYSERR_NOERROR;
549159b3361Sopenharmony_ci			break;
550159b3361Sopenharmony_ci
551159b3361Sopenharmony_ci		default:
552159b3361Sopenharmony_ci			Result = ACMERR_NOTPOSSIBLE;
553159b3361Sopenharmony_ci			break;
554159b3361Sopenharmony_ci	}
555159b3361Sopenharmony_ci
556159b3361Sopenharmony_ci	a_FormatDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
557159b3361Sopenharmony_ci
558159b3361Sopenharmony_ci	return Result;
559159b3361Sopenharmony_ci}
560159b3361Sopenharmony_ci
561159b3361Sopenharmony_ci/*!
562159b3361Sopenharmony_ci	Retreive the details of each known format by this ACM driver
563159b3361Sopenharmony_ci	The index represent the specified format (0 = MP3 / 1 = PCM)
564159b3361Sopenharmony_ci
565159b3361Sopenharmony_ci	\param a_FormatTagDetails will be filled with all the corresponding data
566159b3361Sopenharmony_ci*/
567159b3361Sopenharmony_ciinline DWORD ACM::OnFormatTagDetails(LPACMFORMATTAGDETAILS a_FormatTagDetails, const LPARAM a_Query)
568159b3361Sopenharmony_ci{
569159b3361Sopenharmony_ci	DWORD Result;
570159b3361Sopenharmony_ci	DWORD the_format = WAVE_FORMAT_UNKNOWN; // the format to give details
571159b3361Sopenharmony_ci
572159b3361Sopenharmony_ci	if (a_FormatTagDetails->cbStruct >= sizeof(*a_FormatTagDetails)) {
573159b3361Sopenharmony_ci
574159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACMDM_FORMATTAG_DETAILS, a_Query = 0x%08X",a_Query);
575159b3361Sopenharmony_ci		switch(a_Query & ACM_FORMATTAGDETAILSF_QUERYMASK) {
576159b3361Sopenharmony_ci
577159b3361Sopenharmony_ci			case ACM_FORMATTAGDETAILSF_INDEX:
578159b3361Sopenharmony_ci			// Fill-in the informations corresponding to the a_FormatDetails->dwFormatTagIndex
579159b3361Sopenharmony_ci				my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "get ACM_FORMATTAGDETAILSF_INDEX for index %03d",a_FormatTagDetails->dwFormatTagIndex);
580159b3361Sopenharmony_ci
581159b3361Sopenharmony_ci				if (a_FormatTagDetails->dwFormatTagIndex < FORMAT_TAG_MAX_NB) {
582159b3361Sopenharmony_ci					switch (a_FormatTagDetails->dwFormatTagIndex)
583159b3361Sopenharmony_ci					{
584159b3361Sopenharmony_ci					case 0:
585159b3361Sopenharmony_ci						the_format = PERSONAL_FORMAT;
586159b3361Sopenharmony_ci						break;
587159b3361Sopenharmony_ci					default :
588159b3361Sopenharmony_ci						the_format = WAVE_FORMAT_PCM;
589159b3361Sopenharmony_ci						break;
590159b3361Sopenharmony_ci					}
591159b3361Sopenharmony_ci				}
592159b3361Sopenharmony_ci				else
593159b3361Sopenharmony_ci				{
594159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATTAGDETAILSF_INDEX for unsupported index %03d",a_FormatTagDetails->dwFormatTagIndex);
595159b3361Sopenharmony_ci					Result = ACMERR_NOTPOSSIBLE;
596159b3361Sopenharmony_ci				}
597159b3361Sopenharmony_ci				break;
598159b3361Sopenharmony_ci
599159b3361Sopenharmony_ci			case ACM_FORMATTAGDETAILSF_FORMATTAG:
600159b3361Sopenharmony_ci			// Fill-in the informations corresponding to the a_FormatDetails->dwFormatTagIndex and hdrvr given
601159b3361Sopenharmony_ci				switch (a_FormatTagDetails->dwFormatTag)
602159b3361Sopenharmony_ci				{
603159b3361Sopenharmony_ci				case WAVE_FORMAT_PCM:
604159b3361Sopenharmony_ci					the_format = WAVE_FORMAT_PCM;
605159b3361Sopenharmony_ci					break;
606159b3361Sopenharmony_ci				case PERSONAL_FORMAT:
607159b3361Sopenharmony_ci					the_format = PERSONAL_FORMAT;
608159b3361Sopenharmony_ci					break;
609159b3361Sopenharmony_ci				default:
610159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
611159b3361Sopenharmony_ci				}
612159b3361Sopenharmony_ci				my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "get ACM_FORMATTAGDETAILSF_FORMATTAG for index 0x%02X, cStandardFormats = %d",a_FormatTagDetails->dwFormatTagIndex,a_FormatTagDetails->cStandardFormats);
613159b3361Sopenharmony_ci				break;
614159b3361Sopenharmony_ci			case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
615159b3361Sopenharmony_ci				my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATTAGDETAILSF_LARGESTSIZE not used");
616159b3361Sopenharmony_ci				Result = 0L;
617159b3361Sopenharmony_ci				break;
618159b3361Sopenharmony_ci			default:
619159b3361Sopenharmony_ci				my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails Unknown Format tag query");
620159b3361Sopenharmony_ci				Result = MMSYSERR_NOTSUPPORTED;
621159b3361Sopenharmony_ci				break;
622159b3361Sopenharmony_ci		}
623159b3361Sopenharmony_ci
624159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails the_format = 0x%08X",the_format);
625159b3361Sopenharmony_ci		switch(the_format)
626159b3361Sopenharmony_ci		{
627159b3361Sopenharmony_ci			case WAVE_FORMAT_PCM:
628159b3361Sopenharmony_ci				a_FormatTagDetails->dwFormatTag      = WAVE_FORMAT_PCM;
629159b3361Sopenharmony_ci				a_FormatTagDetails->dwFormatTagIndex = 0;
630159b3361Sopenharmony_ci				a_FormatTagDetails->cbFormatSize     = sizeof(PCMWAVEFORMAT);
631159b3361Sopenharmony_ci				/// \note 0 may mean we don't know how to decode
632159b3361Sopenharmony_ci				a_FormatTagDetails->fdwSupport       = ACMDRIVERDETAILS_SUPPORTF_CODEC;
633159b3361Sopenharmony_ci				a_FormatTagDetails->cStandardFormats = FORMAT_MAX_NB_PCM;
634159b3361Sopenharmony_ci				// should be filled by Windows				a_FormatTagDetails->szFormatTag[0] = '\0';
635159b3361Sopenharmony_ci				Result = MMSYSERR_NOERROR;
636159b3361Sopenharmony_ci				break;
637159b3361Sopenharmony_ci			case PERSONAL_FORMAT:
638159b3361Sopenharmony_ci				a_FormatTagDetails->dwFormatTag      = PERSONAL_FORMAT;
639159b3361Sopenharmony_ci				a_FormatTagDetails->dwFormatTagIndex = 1;
640159b3361Sopenharmony_ci				a_FormatTagDetails->cbFormatSize     = SIZE_FORMAT_STRUCT;
641159b3361Sopenharmony_ci				a_FormatTagDetails->fdwSupport       = ACMDRIVERDETAILS_SUPPORTF_CODEC;
642159b3361Sopenharmony_ci				a_FormatTagDetails->cStandardFormats = GetNumberEncodingFormats();
643159b3361Sopenharmony_ci				lstrcpyW( a_FormatTagDetails->szFormatTag, L"Lame MP3" );
644159b3361Sopenharmony_ci				Result = MMSYSERR_NOERROR;
645159b3361Sopenharmony_ci				break;
646159b3361Sopenharmony_ci			default:
647159b3361Sopenharmony_ci				my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails Unknown format 0x%08X",the_format);
648159b3361Sopenharmony_ci				return (ACMERR_NOTPOSSIBLE);
649159b3361Sopenharmony_ci		}
650159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails %d possibilities for format 0x%08X",a_FormatTagDetails->cStandardFormats,the_format);
651159b3361Sopenharmony_ci	}
652159b3361Sopenharmony_ci	else
653159b3361Sopenharmony_ci	{
654159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "a_FormatTagDetails->cbStruct < sizeof(*a_FormatDetails)");
655159b3361Sopenharmony_ci		Result = ACMERR_NOTPOSSIBLE;
656159b3361Sopenharmony_ci	}
657159b3361Sopenharmony_ci
658159b3361Sopenharmony_ci	return Result;
659159b3361Sopenharmony_ci}
660159b3361Sopenharmony_ci
661159b3361Sopenharmony_ci/*!
662159b3361Sopenharmony_ci	Retreive the global details of this ACM driver
663159b3361Sopenharmony_ci
664159b3361Sopenharmony_ci	\param a_DriverDetail will be filled with all the corresponding data
665159b3361Sopenharmony_ci*/
666159b3361Sopenharmony_ciinline DWORD ACM::OnDriverDetails(const HDRVR hdrvr, LPACMDRIVERDETAILS a_DriverDetail)
667159b3361Sopenharmony_ci{
668159b3361Sopenharmony_ci	if (my_hIcon == NULL)
669159b3361Sopenharmony_ci		my_hIcon = LoadIcon(GetDriverModuleHandle(hdrvr), MAKEINTRESOURCE(IDI_ICON));
670159b3361Sopenharmony_ci	a_DriverDetail->hicon       = my_hIcon;
671159b3361Sopenharmony_ci
672159b3361Sopenharmony_ci	a_DriverDetail->fccType     = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
673159b3361Sopenharmony_ci	a_DriverDetail->fccComp     = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
674159b3361Sopenharmony_ci
675159b3361Sopenharmony_ci	/// \note this is an explicit hack of the FhG values
676159b3361Sopenharmony_ci	/// \note later it could be a new value when the decoding is done
677159b3361Sopenharmony_ci	a_DriverDetail->wMid        = MM_FRAUNHOFER_IIS;
678159b3361Sopenharmony_ci	a_DriverDetail->wPid        = MM_FHGIIS_MPEGLAYER3;
679159b3361Sopenharmony_ci
680159b3361Sopenharmony_ci	a_DriverDetail->vdwACM      = VERSION_MSACM;
681159b3361Sopenharmony_ci	a_DriverDetail->vdwDriver   = VERSION_ACM_DRIVER;
682159b3361Sopenharmony_ci	a_DriverDetail->fdwSupport  = ACMDRIVERDETAILS_SUPPORTF_CODEC;
683159b3361Sopenharmony_ci	a_DriverDetail->cFormatTags = FORMAT_TAG_MAX_NB; // 2 : MP3 and PCM
684159b3361Sopenharmony_ci//	a_DriverDetail->cFormatTags = 1; // 2 : MP3 and PCM
685159b3361Sopenharmony_ci	a_DriverDetail->cFilterTags = FILTER_TAG_MAX_NB;
686159b3361Sopenharmony_ci
687159b3361Sopenharmony_ci	lstrcpyW( a_DriverDetail->szShortName, L"LAME MP3" );
688159b3361Sopenharmony_ci	char tmpStr[128];
689159b3361Sopenharmony_ci	wsprintf(tmpStr, "LAME MP3 Codec v%s", GetVersionString());
690159b3361Sopenharmony_ci	int u = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, tmpStr, -1, a_DriverDetail->szLongName, 0);
691159b3361Sopenharmony_ci	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, tmpStr, -1, a_DriverDetail->szLongName, u);
692159b3361Sopenharmony_ci	lstrcpyW( a_DriverDetail->szCopyright, L"2002 Steve Lhomme" );
693159b3361Sopenharmony_ci	lstrcpyW( a_DriverDetail->szLicensing, L"LGPL (see gnu.org)" );
694159b3361Sopenharmony_ci	/// \todo update this part when the code changes
695159b3361Sopenharmony_ci	lstrcpyW( a_DriverDetail->szFeatures , L"only CBR implementation" );
696159b3361Sopenharmony_ci
697159b3361Sopenharmony_ci    return MMSYSERR_NOERROR;  // Can also return DRVCNF_CANCEL
698159b3361Sopenharmony_ci}
699159b3361Sopenharmony_ci
700159b3361Sopenharmony_ci/*!
701159b3361Sopenharmony_ci	Suggest an output format for the specified input format
702159b3361Sopenharmony_ci
703159b3361Sopenharmony_ci	\param a_FormatSuggest will be filled with all the corresponding data
704159b3361Sopenharmony_ci*/
705159b3361Sopenharmony_ciinline DWORD ACM::OnFormatSuggest(LPACMDRVFORMATSUGGEST a_FormatSuggest)
706159b3361Sopenharmony_ci{
707159b3361Sopenharmony_ci	DWORD Result = MMSYSERR_NOTSUPPORTED;
708159b3361Sopenharmony_ci    DWORD fdwSuggest = (ACM_FORMATSUGGESTF_TYPEMASK & a_FormatSuggest->fdwSuggest);
709159b3361Sopenharmony_ci
710159b3361Sopenharmony_cimy_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest %s%s%s%s (0x%08X)",
711159b3361Sopenharmony_ci				 (fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS) ? "channels, ":"",
712159b3361Sopenharmony_ci				 (fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC) ? "samples/sec, ":"",
713159b3361Sopenharmony_ci				 (fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE) ? "bits/sample, ":"",
714159b3361Sopenharmony_ci				 (fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) ? "format, ":"",
715159b3361Sopenharmony_ci				 fdwSuggest);
716159b3361Sopenharmony_ci
717159b3361Sopenharmony_cimy_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest for source format = 0x%04X, channels = %d, Samples/s = %d, AvgB/s = %d, BlockAlign = %d, b/sample = %d",
718159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxSrc->wFormatTag,
719159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxSrc->nChannels,
720159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxSrc->nSamplesPerSec,
721159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxSrc->nAvgBytesPerSec,
722159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxSrc->nBlockAlign,
723159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxSrc->wBitsPerSample);
724159b3361Sopenharmony_ci
725159b3361Sopenharmony_cimy_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggested destination format = 0x%04X, channels = %d, Samples/s = %d, AvgB/s = %d, BlockAlign = %d, b/sample = %d",
726159b3361Sopenharmony_ci			 a_FormatSuggest->pwfxDst->wFormatTag,
727159b3361Sopenharmony_ci			 a_FormatSuggest->pwfxDst->nChannels,
728159b3361Sopenharmony_ci			 a_FormatSuggest->pwfxDst->nSamplesPerSec,
729159b3361Sopenharmony_ci			 a_FormatSuggest->pwfxDst->nAvgBytesPerSec,
730159b3361Sopenharmony_ci			 a_FormatSuggest->pwfxDst->nBlockAlign,
731159b3361Sopenharmony_ci			 a_FormatSuggest->pwfxDst->wBitsPerSample);
732159b3361Sopenharmony_ci
733159b3361Sopenharmony_ci	switch (a_FormatSuggest->pwfxSrc->wFormatTag)
734159b3361Sopenharmony_ci	{
735159b3361Sopenharmony_ci        case WAVE_FORMAT_PCM:
736159b3361Sopenharmony_ci			/// \todo handle here the decoding ?
737159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest for PCM source");
738159b3361Sopenharmony_ci            //
739159b3361Sopenharmony_ci			//  if the destination format tag is restricted, verify that
740159b3361Sopenharmony_ci			//  it is within our capabilities...
741159b3361Sopenharmony_ci			//
742159b3361Sopenharmony_ci			//  this driver is able to decode to PCM
743159b3361Sopenharmony_ci			//
744159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
745159b3361Sopenharmony_ci            {
746159b3361Sopenharmony_ci                if (PERSONAL_FORMAT != a_FormatSuggest->pwfxDst->wFormatTag)
747159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
748159b3361Sopenharmony_ci            }
749159b3361Sopenharmony_ci            else
750159b3361Sopenharmony_ci			{
751159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->wFormatTag = PERSONAL_FORMAT;
752159b3361Sopenharmony_ci            }
753159b3361Sopenharmony_ci
754159b3361Sopenharmony_ci
755159b3361Sopenharmony_cimy_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed A");
756159b3361Sopenharmony_ci            //
757159b3361Sopenharmony_ci			//  if the destination channel count is restricted, verify that
758159b3361Sopenharmony_ci			//  it is within our capabilities...
759159b3361Sopenharmony_ci			//
760159b3361Sopenharmony_ci			//  this driver is not able to change the number of channels
761159b3361Sopenharmony_ci			//
762159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
763159b3361Sopenharmony_ci            {
764159b3361Sopenharmony_ci                if (a_FormatSuggest->pwfxSrc->nChannels != a_FormatSuggest->pwfxDst->nChannels)
765159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
766159b3361Sopenharmony_ci            }
767159b3361Sopenharmony_ci            else
768159b3361Sopenharmony_ci			{
769159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->nChannels = a_FormatSuggest->pwfxSrc->nChannels;
770159b3361Sopenharmony_ci            }
771159b3361Sopenharmony_ci
772159b3361Sopenharmony_ci			if (a_FormatSuggest->pwfxSrc->nChannels != 1 && a_FormatSuggest->pwfxSrc->nChannels != 2)
773159b3361Sopenharmony_ci				return MMSYSERR_INVALPARAM;
774159b3361Sopenharmony_ci
775159b3361Sopenharmony_ci
776159b3361Sopenharmony_cimy_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed B");
777159b3361Sopenharmony_ci            //
778159b3361Sopenharmony_ci			//  if the destination samples per second is restricted, verify
779159b3361Sopenharmony_ci			//  that it is within our capabilities...
780159b3361Sopenharmony_ci			//
781159b3361Sopenharmony_ci			//  this driver is not able to change the sample rate
782159b3361Sopenharmony_ci			//
783159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
784159b3361Sopenharmony_ci            {
785159b3361Sopenharmony_ci                if (a_FormatSuggest->pwfxSrc->nSamplesPerSec != a_FormatSuggest->pwfxDst->nSamplesPerSec)
786159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
787159b3361Sopenharmony_ci            }
788159b3361Sopenharmony_ci            else
789159b3361Sopenharmony_ci			{
790159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->nSamplesPerSec = a_FormatSuggest->pwfxSrc->nSamplesPerSec;
791159b3361Sopenharmony_ci            }
792159b3361Sopenharmony_ci
793159b3361Sopenharmony_ci
794159b3361Sopenharmony_cimy_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed C");
795159b3361Sopenharmony_ci            //
796159b3361Sopenharmony_ci			//  if the destination bits per sample is restricted, verify
797159b3361Sopenharmony_ci			//  that it is within our capabilities...
798159b3361Sopenharmony_ci			//
799159b3361Sopenharmony_ci			//  We prefer decoding to 16-bit PCM.
800159b3361Sopenharmony_ci			//
801159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
802159b3361Sopenharmony_ci            {
803159b3361Sopenharmony_ci                if ( (16 != a_FormatSuggest->pwfxDst->wBitsPerSample) && (8 != a_FormatSuggest->pwfxDst->wBitsPerSample) )
804159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
805159b3361Sopenharmony_ci            }
806159b3361Sopenharmony_ci            else
807159b3361Sopenharmony_ci			{
808159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->wBitsPerSample = 16;
809159b3361Sopenharmony_ci            }
810159b3361Sopenharmony_ci
811159b3361Sopenharmony_ci			//			a_FormatSuggest->pwfxDst->nBlockAlign = FORMAT_BLOCK_ALIGN;
812159b3361Sopenharmony_ci			a_FormatSuggest->pwfxDst->nBlockAlign = a_FormatSuggest->pwfxDst->nChannels * a_FormatSuggest->pwfxDst->wBitsPerSample / 8;
813159b3361Sopenharmony_ci
814159b3361Sopenharmony_ci			a_FormatSuggest->pwfxDst->nAvgBytesPerSec = a_FormatSuggest->pwfxDst->nChannels * 64000 / 8;
815159b3361Sopenharmony_ci
816159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed");
817159b3361Sopenharmony_ci			Result = MMSYSERR_NOERROR;
818159b3361Sopenharmony_ci
819159b3361Sopenharmony_ci
820159b3361Sopenharmony_ci			break;
821159b3361Sopenharmony_ci		case PERSONAL_FORMAT:
822159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest for PERSONAL source");
823159b3361Sopenharmony_ci            //
824159b3361Sopenharmony_ci			//  if the destination format tag is restricted, verify that
825159b3361Sopenharmony_ci			//  it is within our capabilities...
826159b3361Sopenharmony_ci			//
827159b3361Sopenharmony_ci			//  this driver is able to decode to PCM
828159b3361Sopenharmony_ci			//
829159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
830159b3361Sopenharmony_ci            {
831159b3361Sopenharmony_ci                if (WAVE_FORMAT_PCM != a_FormatSuggest->pwfxDst->wFormatTag)
832159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
833159b3361Sopenharmony_ci            }
834159b3361Sopenharmony_ci            else
835159b3361Sopenharmony_ci			{
836159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
837159b3361Sopenharmony_ci            }
838159b3361Sopenharmony_ci
839159b3361Sopenharmony_ci
840159b3361Sopenharmony_ci            //
841159b3361Sopenharmony_ci			//  if the destination channel count is restricted, verify that
842159b3361Sopenharmony_ci			//  it is within our capabilities...
843159b3361Sopenharmony_ci			//
844159b3361Sopenharmony_ci			//  this driver is not able to change the number of channels
845159b3361Sopenharmony_ci			//
846159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
847159b3361Sopenharmony_ci            {
848159b3361Sopenharmony_ci                if (a_FormatSuggest->pwfxSrc->nChannels != a_FormatSuggest->pwfxDst->nChannels)
849159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
850159b3361Sopenharmony_ci            }
851159b3361Sopenharmony_ci            else
852159b3361Sopenharmony_ci			{
853159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->nChannels = a_FormatSuggest->pwfxSrc->nChannels;
854159b3361Sopenharmony_ci            }
855159b3361Sopenharmony_ci
856159b3361Sopenharmony_ci
857159b3361Sopenharmony_ci            //
858159b3361Sopenharmony_ci			//  if the destination samples per second is restricted, verify
859159b3361Sopenharmony_ci			//  that it is within our capabilities...
860159b3361Sopenharmony_ci			//
861159b3361Sopenharmony_ci			//  this driver is not able to change the sample rate
862159b3361Sopenharmony_ci			//
863159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
864159b3361Sopenharmony_ci            {
865159b3361Sopenharmony_ci                if (a_FormatSuggest->pwfxSrc->nSamplesPerSec != a_FormatSuggest->pwfxDst->nSamplesPerSec)
866159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
867159b3361Sopenharmony_ci            }
868159b3361Sopenharmony_ci            else
869159b3361Sopenharmony_ci			{
870159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->nSamplesPerSec = a_FormatSuggest->pwfxSrc->nSamplesPerSec;
871159b3361Sopenharmony_ci            }
872159b3361Sopenharmony_ci
873159b3361Sopenharmony_ci
874159b3361Sopenharmony_ci            //
875159b3361Sopenharmony_ci			//  if the destination bits per sample is restricted, verify
876159b3361Sopenharmony_ci			//  that it is within our capabilities...
877159b3361Sopenharmony_ci			//
878159b3361Sopenharmony_ci			//  We prefer decoding to 16-bit PCM.
879159b3361Sopenharmony_ci			//
880159b3361Sopenharmony_ci			if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
881159b3361Sopenharmony_ci            {
882159b3361Sopenharmony_ci                if ( (16 != a_FormatSuggest->pwfxDst->wBitsPerSample) && (8 != a_FormatSuggest->pwfxDst->wBitsPerSample) )
883159b3361Sopenharmony_ci                    return (ACMERR_NOTPOSSIBLE);
884159b3361Sopenharmony_ci            }
885159b3361Sopenharmony_ci            else
886159b3361Sopenharmony_ci			{
887159b3361Sopenharmony_ci                a_FormatSuggest->pwfxDst->wBitsPerSample = 16;
888159b3361Sopenharmony_ci            }
889159b3361Sopenharmony_ci
890159b3361Sopenharmony_ci			//			a_FormatSuggest->pwfxDst->nBlockAlign = FORMAT_BLOCK_ALIGN;
891159b3361Sopenharmony_ci			a_FormatSuggest->pwfxDst->nBlockAlign = a_FormatSuggest->pwfxDst->nChannels * a_FormatSuggest->pwfxDst->wBitsPerSample / 8;
892159b3361Sopenharmony_ci
893159b3361Sopenharmony_ci			/// \todo this value must be a correct one !
894159b3361Sopenharmony_ci			a_FormatSuggest->pwfxDst->nAvgBytesPerSec = a_FormatSuggest->pwfxDst->nSamplesPerSec * a_FormatSuggest->pwfxDst->nChannels * a_FormatSuggest->pwfxDst->wBitsPerSample / 8;
895159b3361Sopenharmony_ci
896159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed");
897159b3361Sopenharmony_ci			Result = MMSYSERR_NOERROR;
898159b3361Sopenharmony_ci
899159b3361Sopenharmony_ci
900159b3361Sopenharmony_ci			break;
901159b3361Sopenharmony_ci	}
902159b3361Sopenharmony_ci
903159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggested destination format = 0x%04X, channels = %d, Samples/s = %d, AvgB/s = %d, BlockAlign = %d, b/sample = %d",
904159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxDst->wFormatTag,
905159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxDst->nChannels,
906159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxDst->nSamplesPerSec,
907159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxDst->nAvgBytesPerSec,
908159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxDst->nBlockAlign,
909159b3361Sopenharmony_ci				 a_FormatSuggest->pwfxDst->wBitsPerSample);
910159b3361Sopenharmony_ci
911159b3361Sopenharmony_ci	return Result;
912159b3361Sopenharmony_ci}
913159b3361Sopenharmony_ci
914159b3361Sopenharmony_ci/*!
915159b3361Sopenharmony_ci	Create a stream instance for decoding/encoding
916159b3361Sopenharmony_ci
917159b3361Sopenharmony_ci	\param a_StreamInstance contain information about the stream desired
918159b3361Sopenharmony_ci*/
919159b3361Sopenharmony_ciinline DWORD ACM::OnStreamOpen(LPACMDRVSTREAMINSTANCE a_StreamInstance)
920159b3361Sopenharmony_ci{
921159b3361Sopenharmony_ci	DWORD Result = ACMERR_NOTPOSSIBLE;
922159b3361Sopenharmony_ci
923159b3361Sopenharmony_ci	//
924159b3361Sopenharmony_ci	//  the most important condition to check before doing anything else
925159b3361Sopenharmony_ci	//  is that this ACM driver can actually perform the conversion we are
926159b3361Sopenharmony_ci	//  being opened for. this check should fail as quickly as possible
927159b3361Sopenharmony_ci	//  if the conversion is not possible by this driver.
928159b3361Sopenharmony_ci	//
929159b3361Sopenharmony_ci	//  it is VERY important to fail quickly so the ACM can attempt to
930159b3361Sopenharmony_ci	//  find a driver that is suitable for the conversion. also note that
931159b3361Sopenharmony_ci	//  the ACM may call this driver several times with slightly different
932159b3361Sopenharmony_ci	//  format specifications before giving up.
933159b3361Sopenharmony_ci	//
934159b3361Sopenharmony_ci	//  this driver first verifies that the source and destination formats
935159b3361Sopenharmony_ci	//  are acceptable...
936159b3361Sopenharmony_ci	//
937159b3361Sopenharmony_ci	switch (a_StreamInstance->pwfxSrc->wFormatTag)
938159b3361Sopenharmony_ci	{
939159b3361Sopenharmony_ci        case WAVE_FORMAT_PCM:
940159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream for PCM source (%05d samples %d channels %d bits/sample)",a_StreamInstance->pwfxSrc->nSamplesPerSec,a_StreamInstance->pwfxSrc->nChannels,a_StreamInstance->pwfxSrc->wBitsPerSample);
941159b3361Sopenharmony_ci			if (a_StreamInstance->pwfxDst->wFormatTag == PERSONAL_FORMAT)
942159b3361Sopenharmony_ci			{
943159b3361Sopenharmony_ci				unsigned int OutputFrequency;
944159b3361Sopenharmony_ci
945159b3361Sopenharmony_ci				/// \todo Smart mode
946159b3361Sopenharmony_ci				if (my_EncodingProperties.GetSmartOutputMode())
947159b3361Sopenharmony_ci					OutputFrequency = ACMStream::GetOutputSampleRate(a_StreamInstance->pwfxSrc->nSamplesPerSec,a_StreamInstance->pwfxDst->nAvgBytesPerSec,a_StreamInstance->pwfxDst->nChannels);
948159b3361Sopenharmony_ci				else
949159b3361Sopenharmony_ci					OutputFrequency = a_StreamInstance->pwfxSrc->nSamplesPerSec;
950159b3361Sopenharmony_ci
951159b3361Sopenharmony_ci				my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream for PERSONAL output (%05d samples %d channels %d bits/sample %d kbps)",a_StreamInstance->pwfxDst->nSamplesPerSec,a_StreamInstance->pwfxDst->nChannels,a_StreamInstance->pwfxDst->wBitsPerSample,8 * a_StreamInstance->pwfxDst->nAvgBytesPerSec);
952159b3361Sopenharmony_ci
953159b3361Sopenharmony_ci				/// \todo add the possibility to have channel resampling (mono to stereo / stereo to mono)
954159b3361Sopenharmony_ci				/// \todo support resampling ?
955159b3361Sopenharmony_ci				/// \todo only do the test on OutputFrequency in "Smart Output" mode
956159b3361Sopenharmony_ci				if (a_StreamInstance->pwfxDst->nSamplesPerSec != OutputFrequency ||
957159b3361Sopenharmony_ci//					a_StreamInstance->pwfxSrc->nSamplesPerSec != a_StreamInstance->pwfxDst->nSamplesPerSec ||
958159b3361Sopenharmony_ci					a_StreamInstance->pwfxSrc->nChannels != a_StreamInstance->pwfxDst->nChannels ||
959159b3361Sopenharmony_ci					a_StreamInstance->pwfxSrc->wBitsPerSample != 16)
960159b3361Sopenharmony_ci				{
961159b3361Sopenharmony_ci					Result = ACMERR_NOTPOSSIBLE;
962159b3361Sopenharmony_ci				} else {
963159b3361Sopenharmony_ci					if ((a_StreamInstance->fdwOpen & ACM_STREAMOPENF_QUERY) == 0)
964159b3361Sopenharmony_ci					{
965159b3361Sopenharmony_ci						ACMStream * the_stream = ACMStream::Create();
966159b3361Sopenharmony_ci						a_StreamInstance->dwInstance = (DWORD) the_stream;
967159b3361Sopenharmony_ci
968159b3361Sopenharmony_ci						if (the_stream != NULL)
969159b3361Sopenharmony_ci						{
970159b3361Sopenharmony_ci							MPEGLAYER3WAVEFORMAT * casted = (MPEGLAYER3WAVEFORMAT *) a_StreamInstance->pwfxDst;
971159b3361Sopenharmony_ci							vbr_mode a_mode = (casted->fdwFlags-2 == 0)?vbr_abr:vbr_off;
972159b3361Sopenharmony_ci							if (the_stream->init(a_StreamInstance->pwfxDst->nSamplesPerSec,
973159b3361Sopenharmony_ci												 OutputFrequency,
974159b3361Sopenharmony_ci												 a_StreamInstance->pwfxDst->nChannels,
975159b3361Sopenharmony_ci												 a_StreamInstance->pwfxDst->nAvgBytesPerSec,
976159b3361Sopenharmony_ci												 a_mode))
977159b3361Sopenharmony_ci								Result = MMSYSERR_NOERROR;
978159b3361Sopenharmony_ci							else
979159b3361Sopenharmony_ci								ACMStream::Erase( the_stream );
980159b3361Sopenharmony_ci						}
981159b3361Sopenharmony_ci					}
982159b3361Sopenharmony_ci					else
983159b3361Sopenharmony_ci					{
984159b3361Sopenharmony_ci						Result = MMSYSERR_NOERROR;
985159b3361Sopenharmony_ci					}
986159b3361Sopenharmony_ci				}
987159b3361Sopenharmony_ci			}
988159b3361Sopenharmony_ci			break;
989159b3361Sopenharmony_ci		case PERSONAL_FORMAT:
990159b3361Sopenharmony_ci			my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream for PERSONAL source (%05d samples %d channels %d bits/sample %d kbps)",a_StreamInstance->pwfxSrc->nSamplesPerSec,a_StreamInstance->pwfxSrc->nChannels,a_StreamInstance->pwfxSrc->wBitsPerSample,8 * a_StreamInstance->pwfxSrc->nAvgBytesPerSec);
991159b3361Sopenharmony_ci			if (a_StreamInstance->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
992159b3361Sopenharmony_ci			{
993159b3361Sopenharmony_ci#ifdef ENABLE_DECODING
994159b3361Sopenharmony_ci				if ((a_StreamInstance->fdwOpen & ACM_STREAMOPENF_QUERY) == 0)
995159b3361Sopenharmony_ci				{
996159b3361Sopenharmony_ci					/// \todo create the decoding stream
997159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream for PCM output (%05d samples %d channels %d bits/sample %d B/s)",a_StreamInstance->pwfxDst->nSamplesPerSec,a_StreamInstance->pwfxDst->nChannels,a_StreamInstance->pwfxDst->wBitsPerSample,a_StreamInstance->pwfxDst->nAvgBytesPerSec);
998159b3361Sopenharmony_ci
999159b3361Sopenharmony_ci					DecodeStream * the_stream = DecodeStream::Create();
1000159b3361Sopenharmony_ci					a_StreamInstance->dwInstance = (DWORD) the_stream;
1001159b3361Sopenharmony_ci
1002159b3361Sopenharmony_ci					if (the_stream != NULL)
1003159b3361Sopenharmony_ci					{
1004159b3361Sopenharmony_ci						if (the_stream->init(a_StreamInstance->pwfxDst->nSamplesPerSec,
1005159b3361Sopenharmony_ci											 a_StreamInstance->pwfxDst->nChannels,
1006159b3361Sopenharmony_ci											 a_StreamInstance->pwfxDst->nAvgBytesPerSec,
1007159b3361Sopenharmony_ci											 a_StreamInstance->pwfxSrc->nAvgBytesPerSec))
1008159b3361Sopenharmony_ci							Result = MMSYSERR_NOERROR;
1009159b3361Sopenharmony_ci						else
1010159b3361Sopenharmony_ci							DecodeStream::Erase( the_stream );
1011159b3361Sopenharmony_ci					}
1012159b3361Sopenharmony_ci				}
1013159b3361Sopenharmony_ci				else
1014159b3361Sopenharmony_ci				{
1015159b3361Sopenharmony_ci					/// \todo decoding verification
1016159b3361Sopenharmony_ci					my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream is valid");
1017159b3361Sopenharmony_ci					Result = MMSYSERR_NOERROR;
1018159b3361Sopenharmony_ci				}
1019159b3361Sopenharmony_ci#endif // ENABLE_DECODING
1020159b3361Sopenharmony_ci			}
1021159b3361Sopenharmony_ci			break;
1022159b3361Sopenharmony_ci	}
1023159b3361Sopenharmony_ci
1024159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream Result = %d",Result);
1025159b3361Sopenharmony_ci	return Result;
1026159b3361Sopenharmony_ci}
1027159b3361Sopenharmony_ci
1028159b3361Sopenharmony_ciinline DWORD ACM::OnStreamSize(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMDRVSTREAMSIZE the_StreamSize)
1029159b3361Sopenharmony_ci{
1030159b3361Sopenharmony_ci	DWORD Result = ACMERR_NOTPOSSIBLE;
1031159b3361Sopenharmony_ci
1032159b3361Sopenharmony_ci    switch (ACM_STREAMSIZEF_QUERYMASK & the_StreamSize->fdwSize)
1033159b3361Sopenharmony_ci    {
1034159b3361Sopenharmony_ci	case ACM_STREAMSIZEF_DESTINATION:
1035159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Get source buffer size for destination size = %d",the_StreamSize->cbDstLength);
1036159b3361Sopenharmony_ci		break;
1037159b3361Sopenharmony_ci	case ACM_STREAMSIZEF_SOURCE:
1038159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Get destination buffer size for source size = %d",the_StreamSize->cbSrcLength);
1039159b3361Sopenharmony_ci        if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
1040159b3361Sopenharmony_ci			PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
1041159b3361Sopenharmony_ci        {
1042159b3361Sopenharmony_ci			ACMStream * the_stream = (ACMStream *) a_StreamInstance->dwInstance;
1043159b3361Sopenharmony_ci			if (the_stream != NULL)
1044159b3361Sopenharmony_ci			{
1045159b3361Sopenharmony_ci				the_StreamSize->cbDstLength = the_stream->GetOutputSizeForInput(the_StreamSize->cbSrcLength);
1046159b3361Sopenharmony_ci				Result = MMSYSERR_NOERROR;
1047159b3361Sopenharmony_ci			}
1048159b3361Sopenharmony_ci		}
1049159b3361Sopenharmony_ci        else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
1050159b3361Sopenharmony_ci			 WAVE_FORMAT_PCM== a_StreamInstance->pwfxDst->wFormatTag)
1051159b3361Sopenharmony_ci		{
1052159b3361Sopenharmony_ci#ifdef ENABLE_DECODING
1053159b3361Sopenharmony_ci			DecodeStream * the_stream = (DecodeStream *) a_StreamInstance->dwInstance;
1054159b3361Sopenharmony_ci			if (the_stream != NULL)
1055159b3361Sopenharmony_ci			{
1056159b3361Sopenharmony_ci				the_StreamSize->cbDstLength = the_stream->GetOutputSizeForInput(the_StreamSize->cbSrcLength);
1057159b3361Sopenharmony_ci				Result = MMSYSERR_NOERROR;
1058159b3361Sopenharmony_ci			}
1059159b3361Sopenharmony_ci#endif // ENABLE_DECODING
1060159b3361Sopenharmony_ci		}
1061159b3361Sopenharmony_ci		break;
1062159b3361Sopenharmony_ci	default:
1063159b3361Sopenharmony_ci		Result = MMSYSERR_INVALFLAG;
1064159b3361Sopenharmony_ci		break;
1065159b3361Sopenharmony_ci	}
1066159b3361Sopenharmony_ci
1067159b3361Sopenharmony_ci	return Result;
1068159b3361Sopenharmony_ci}
1069159b3361Sopenharmony_ci
1070159b3361Sopenharmony_ciinline DWORD ACM::OnStreamClose(LPACMDRVSTREAMINSTANCE a_StreamInstance)
1071159b3361Sopenharmony_ci{
1072159b3361Sopenharmony_ci	DWORD Result = ACMERR_NOTPOSSIBLE;
1073159b3361Sopenharmony_ci
1074159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamClose the stream 0x%X",a_StreamInstance->dwInstance);
1075159b3361Sopenharmony_ci    if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
1076159b3361Sopenharmony_ci		PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
1077159b3361Sopenharmony_ci    {
1078159b3361Sopenharmony_ci	ACMStream::Erase( (ACMStream *) a_StreamInstance->dwInstance );
1079159b3361Sopenharmony_ci	}
1080159b3361Sopenharmony_ci    else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
1081159b3361Sopenharmony_ci		 WAVE_FORMAT_PCM== a_StreamInstance->pwfxDst->wFormatTag)
1082159b3361Sopenharmony_ci    {
1083159b3361Sopenharmony_ci#ifdef ENABLE_DECODING
1084159b3361Sopenharmony_ci		DecodeStream::Erase( (DecodeStream *) a_StreamInstance->dwInstance );
1085159b3361Sopenharmony_ci#endif // ENABLE_DECODING
1086159b3361Sopenharmony_ci	}
1087159b3361Sopenharmony_ci
1088159b3361Sopenharmony_ci	// nothing to do yet
1089159b3361Sopenharmony_ci	Result = MMSYSERR_NOERROR;
1090159b3361Sopenharmony_ci
1091159b3361Sopenharmony_ci	return Result;
1092159b3361Sopenharmony_ci}
1093159b3361Sopenharmony_ci
1094159b3361Sopenharmony_ciinline DWORD ACM::OnStreamPrepareHeader(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMSTREAMHEADER a_StreamHeader)
1095159b3361Sopenharmony_ci{
1096159b3361Sopenharmony_ci	DWORD Result = ACMERR_NOTPOSSIBLE;
1097159b3361Sopenharmony_ci
1098159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "  prepare : Src : %d (0x%08X) / %d - Dst : %d (0x%08X) / %d"
1099159b3361Sopenharmony_ci												, a_StreamHeader->cbSrcLength
1100159b3361Sopenharmony_ci												, a_StreamHeader->pbSrc
1101159b3361Sopenharmony_ci												, a_StreamHeader->cbSrcLengthUsed
1102159b3361Sopenharmony_ci												, a_StreamHeader->cbDstLength
1103159b3361Sopenharmony_ci												, a_StreamHeader->pbDst
1104159b3361Sopenharmony_ci												, a_StreamHeader->cbDstLengthUsed
1105159b3361Sopenharmony_ci											  );
1106159b3361Sopenharmony_ci
1107159b3361Sopenharmony_ci	if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
1108159b3361Sopenharmony_ci		PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
1109159b3361Sopenharmony_ci	{
1110159b3361Sopenharmony_ci		ACMStream * the_stream = (ACMStream *)a_StreamInstance->dwInstance;
1111159b3361Sopenharmony_ci
1112159b3361Sopenharmony_ci		if (the_stream->open(my_EncodingProperties))
1113159b3361Sopenharmony_ci			Result = MMSYSERR_NOERROR;
1114159b3361Sopenharmony_ci	}
1115159b3361Sopenharmony_ci	else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
1116159b3361Sopenharmony_ci		     WAVE_FORMAT_PCM == a_StreamInstance->pwfxDst->wFormatTag)
1117159b3361Sopenharmony_ci	{
1118159b3361Sopenharmony_ci#ifdef ENABLE_DECODING
1119159b3361Sopenharmony_ci		DecodeStream * the_stream = (DecodeStream *)a_StreamInstance->dwInstance;
1120159b3361Sopenharmony_ci
1121159b3361Sopenharmony_ci		if (the_stream->open())
1122159b3361Sopenharmony_ci			Result = MMSYSERR_NOERROR;
1123159b3361Sopenharmony_ci#endif // ENABLE_DECODING
1124159b3361Sopenharmony_ci	}
1125159b3361Sopenharmony_ci
1126159b3361Sopenharmony_ci	return Result;
1127159b3361Sopenharmony_ci}
1128159b3361Sopenharmony_ci
1129159b3361Sopenharmony_ciinline DWORD ACM::OnStreamUnPrepareHeader(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMSTREAMHEADER a_StreamHeader)
1130159b3361Sopenharmony_ci{
1131159b3361Sopenharmony_ci	DWORD Result = ACMERR_NOTPOSSIBLE;
1132159b3361Sopenharmony_ci
1133159b3361Sopenharmony_ci	my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "unprepare : Src : %d / %d - Dst : %d / %d"
1134159b3361Sopenharmony_ci											, a_StreamHeader->cbSrcLength
1135159b3361Sopenharmony_ci											, a_StreamHeader->cbSrcLengthUsed
1136159b3361Sopenharmony_ci											, a_StreamHeader->cbDstLength
1137159b3361Sopenharmony_ci											, a_StreamHeader->cbDstLengthUsed
1138159b3361Sopenharmony_ci											);
1139159b3361Sopenharmony_ci    if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
1140159b3361Sopenharmony_ci		PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
1141159b3361Sopenharmony_ci    {
1142159b3361Sopenharmony_ci	ACMStream * the_stream = (ACMStream *)a_StreamInstance->dwInstance;
1143159b3361Sopenharmony_ci	DWORD OutputSize = a_StreamHeader->cbDstLength;
1144159b3361Sopenharmony_ci
1145159b3361Sopenharmony_ci	if (the_stream->close(a_StreamHeader->pbDst, &OutputSize) && (OutputSize <= a_StreamHeader->cbDstLength))
1146159b3361Sopenharmony_ci	{
1147159b3361Sopenharmony_ci		a_StreamHeader->cbDstLengthUsed = OutputSize;
1148159b3361Sopenharmony_ci			Result = MMSYSERR_NOERROR;
1149159b3361Sopenharmony_ci		}
1150159b3361Sopenharmony_ci	}
1151159b3361Sopenharmony_ci    else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
1152159b3361Sopenharmony_ci		 WAVE_FORMAT_PCM== a_StreamInstance->pwfxDst->wFormatTag)
1153159b3361Sopenharmony_ci    {
1154159b3361Sopenharmony_ci#ifdef ENABLE_DECODING
1155159b3361Sopenharmony_ci		DecodeStream * the_stream = (DecodeStream *)a_StreamInstance->dwInstance;
1156159b3361Sopenharmony_ci		DWORD OutputSize = a_StreamHeader->cbDstLength;
1157159b3361Sopenharmony_ci
1158159b3361Sopenharmony_ci		if (the_stream->close(a_StreamHeader->pbDst, &OutputSize) && (OutputSize <= a_StreamHeader->cbDstLength))
1159159b3361Sopenharmony_ci		{
1160159b3361Sopenharmony_ci			a_StreamHeader->cbDstLengthUsed = OutputSize;
1161159b3361Sopenharmony_ci			Result = MMSYSERR_NOERROR;
1162159b3361Sopenharmony_ci	}
1163159b3361Sopenharmony_ci#endif // ENABLE_DECODING
1164159b3361Sopenharmony_ci	}
1165159b3361Sopenharmony_ci
1166159b3361Sopenharmony_ci	return Result;
1167159b3361Sopenharmony_ci}
1168159b3361Sopenharmony_ci
1169159b3361Sopenharmony_ciinline DWORD ACM::OnStreamConvert(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMDRVSTREAMHEADER a_StreamHeader)
1170159b3361Sopenharmony_ci{
1171159b3361Sopenharmony_ci	DWORD Result = ACMERR_NOTPOSSIBLE;
1172159b3361Sopenharmony_ci
1173159b3361Sopenharmony_ci	if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
1174159b3361Sopenharmony_ci		PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
1175159b3361Sopenharmony_ci	{
1176159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamConvert SRC = PCM (encode)");
1177159b3361Sopenharmony_ci
1178159b3361Sopenharmony_ci		ACMStream * the_stream = (ACMStream *) a_StreamInstance->dwInstance;
1179159b3361Sopenharmony_ci		if (the_stream != NULL)
1180159b3361Sopenharmony_ci		{
1181159b3361Sopenharmony_ci			if (the_stream->ConvertBuffer( a_StreamHeader ))
1182159b3361Sopenharmony_ci				Result = MMSYSERR_NOERROR;
1183159b3361Sopenharmony_ci		}
1184159b3361Sopenharmony_ci	}
1185159b3361Sopenharmony_ci	else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
1186159b3361Sopenharmony_ci		     WAVE_FORMAT_PCM == a_StreamInstance->pwfxDst->wFormatTag)
1187159b3361Sopenharmony_ci	{
1188159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamConvert SRC = MP3 (decode)");
1189159b3361Sopenharmony_ci
1190159b3361Sopenharmony_ci#ifdef ENABLE_DECODING
1191159b3361Sopenharmony_ci		DecodeStream * the_stream = (DecodeStream *) a_StreamInstance->dwInstance;
1192159b3361Sopenharmony_ci		if (the_stream != NULL)
1193159b3361Sopenharmony_ci		{
1194159b3361Sopenharmony_ci			if (the_stream->ConvertBuffer( a_StreamHeader ))
1195159b3361Sopenharmony_ci				Result = MMSYSERR_NOERROR;
1196159b3361Sopenharmony_ci		}
1197159b3361Sopenharmony_ci#endif // ENABLE_DECODING
1198159b3361Sopenharmony_ci	}
1199159b3361Sopenharmony_ci	else
1200159b3361Sopenharmony_ci		my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamConvert unsupported conversion");
1201159b3361Sopenharmony_ci
1202159b3361Sopenharmony_ci	return Result;
1203159b3361Sopenharmony_ci}
1204159b3361Sopenharmony_ci
1205159b3361Sopenharmony_ci
1206159b3361Sopenharmony_civoid ACM::GetMP3FormatForIndex(const DWORD the_Index, WAVEFORMATEX & the_Format, unsigned short the_String[ACMFORMATDETAILS_FORMAT_CHARS]) const
1207159b3361Sopenharmony_ci{
1208159b3361Sopenharmony_ci	int Block_size;
1209159b3361Sopenharmony_ci    char temp[ACMFORMATDETAILS_FORMAT_CHARS];
1210159b3361Sopenharmony_ci
1211159b3361Sopenharmony_ci
1212159b3361Sopenharmony_ci	if (the_Index < bitrate_table.size())
1213159b3361Sopenharmony_ci	{
1214159b3361Sopenharmony_ci	//	the_Format.wBitsPerSample = 16;
1215159b3361Sopenharmony_ci		the_Format.wBitsPerSample = 0;
1216159b3361Sopenharmony_ci
1217159b3361Sopenharmony_ci		/// \todo handle more channel modes (mono, stereo, joint-stereo, dual-channel)
1218159b3361Sopenharmony_ci	//	the_Format.nChannels = SIZE_CHANNEL_MODE - int(the_Index % SIZE_CHANNEL_MODE);
1219159b3361Sopenharmony_ci
1220159b3361Sopenharmony_ci		the_Format.nBlockAlign = 1;
1221159b3361Sopenharmony_ci
1222159b3361Sopenharmony_ci		the_Format.nSamplesPerSec = bitrate_table[the_Index].frequency;
1223159b3361Sopenharmony_ci		the_Format.nAvgBytesPerSec = bitrate_table[the_Index].bitrate * 1000 / 8;
1224159b3361Sopenharmony_ci		if (bitrate_table[the_Index].frequency >= mpeg1_freq[SIZE_FREQ_MPEG1-1])
1225159b3361Sopenharmony_ci			Block_size = 1152;
1226159b3361Sopenharmony_ci		else
1227159b3361Sopenharmony_ci			Block_size = 576;
1228159b3361Sopenharmony_ci
1229159b3361Sopenharmony_ci		the_Format.nChannels = bitrate_table[the_Index].channels;
1230159b3361Sopenharmony_ci
1231159b3361Sopenharmony_ci		the_Format.cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
1232159b3361Sopenharmony_ci		MPEGLAYER3WAVEFORMAT * tmpFormat = (MPEGLAYER3WAVEFORMAT *) &the_Format;
1233159b3361Sopenharmony_ci		tmpFormat->wID             = 1;
1234159b3361Sopenharmony_ci		// this is the only way I found to know if we do CBR or ABR
1235159b3361Sopenharmony_ci		tmpFormat->fdwFlags        = 2 + ((bitrate_table[the_Index].mode == vbr_abr)?0:2);
1236159b3361Sopenharmony_ci		tmpFormat->nBlockSize      = Block_size * the_Format.nAvgBytesPerSec / the_Format.nSamplesPerSec;
1237159b3361Sopenharmony_ci		tmpFormat->nFramesPerBlock = 1;
1238159b3361Sopenharmony_ci		tmpFormat->nCodecDelay     = 0; // 0x0571 on FHG
1239159b3361Sopenharmony_ci
1240159b3361Sopenharmony_ci         /// \todo : generate the string with the appropriate stereo mode
1241159b3361Sopenharmony_ci         if (bitrate_table[the_Index].mode == vbr_abr)
1242159b3361Sopenharmony_ci             wsprintfA( temp, "%d Hz, %d kbps ABR, %s", the_Format.nSamplesPerSec, the_Format.nAvgBytesPerSec * 8 / 1000, (the_Format.nChannels == 1)?"Mono":"Stereo");
1243159b3361Sopenharmony_ci         else
1244159b3361Sopenharmony_ci             wsprintfA( temp, "%d Hz, %d kbps CBR, %s", the_Format.nSamplesPerSec, the_Format.nAvgBytesPerSec * 8 / 1000, (the_Format.nChannels == 1)?"Mono":"Stereo");
1245159b3361Sopenharmony_ci
1246159b3361Sopenharmony_ci         MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, temp, -1, the_String, ACMFORMATDETAILS_FORMAT_CHARS);
1247159b3361Sopenharmony_ci     }
1248159b3361Sopenharmony_ci }
1249159b3361Sopenharmony_ci
1250159b3361Sopenharmony_civoid ACM::GetPCMFormatForIndex(const DWORD the_Index, WAVEFORMATEX & the_Format, unsigned short the_String[ACMFORMATDETAILS_FORMAT_CHARS]) const
1251159b3361Sopenharmony_ci{
1252159b3361Sopenharmony_ci	the_Format.nChannels = SIZE_CHANNEL_MODE - int(the_Index % SIZE_CHANNEL_MODE);
1253159b3361Sopenharmony_ci	the_Format.wBitsPerSample = 16;
1254159b3361Sopenharmony_ci	the_Format.nBlockAlign = the_Format.nChannels * the_Format.wBitsPerSample / 8;
1255159b3361Sopenharmony_ci
1256159b3361Sopenharmony_ci
1257159b3361Sopenharmony_ci	DWORD a_Channel_Independent = the_Index / SIZE_CHANNEL_MODE;
1258159b3361Sopenharmony_ci
1259159b3361Sopenharmony_ci	// first MPEG1 frequencies
1260159b3361Sopenharmony_ci	if (a_Channel_Independent < SIZE_FREQ_MPEG1)
1261159b3361Sopenharmony_ci	{
1262159b3361Sopenharmony_ci		the_Format.nSamplesPerSec = mpeg1_freq[a_Channel_Independent];
1263159b3361Sopenharmony_ci	}
1264159b3361Sopenharmony_ci	else
1265159b3361Sopenharmony_ci	{
1266159b3361Sopenharmony_ci		a_Channel_Independent -= SIZE_FREQ_MPEG1;
1267159b3361Sopenharmony_ci		the_Format.nSamplesPerSec = mpeg2_freq[a_Channel_Independent];
1268159b3361Sopenharmony_ci	}
1269159b3361Sopenharmony_ci
1270159b3361Sopenharmony_ci	the_Format.nAvgBytesPerSec = the_Format.nSamplesPerSec * the_Format.nChannels * the_Format.wBitsPerSample / 8;
1271159b3361Sopenharmony_ci}
1272159b3361Sopenharmony_ci
1273159b3361Sopenharmony_ciDWORD ACM::GetNumberEncodingFormats() const
1274159b3361Sopenharmony_ci{
1275159b3361Sopenharmony_ci	return bitrate_table.size();
1276159b3361Sopenharmony_ci}
1277159b3361Sopenharmony_ci
1278159b3361Sopenharmony_cibool ACM::IsSmartOutput(const int frequency, const int bitrate, const int channels) const
1279159b3361Sopenharmony_ci{
1280159b3361Sopenharmony_ci	double compression_ratio = double(frequency * 2 * channels) / double(bitrate * 100);
1281159b3361Sopenharmony_ci
1282159b3361Sopenharmony_ci//my_debug.OutPut(DEBUG_LEVEL_FUNC_DEBUG, "compression_ratio %f, freq %d, bitrate %d, channels %d", compression_ratio, frequency, bitrate, channels);
1283159b3361Sopenharmony_ci
1284159b3361Sopenharmony_ci	if(my_EncodingProperties.GetSmartOutputMode())
1285159b3361Sopenharmony_ci		return (compression_ratio <= my_EncodingProperties.GetSmartRatio());
1286159b3361Sopenharmony_ci	else return true;
1287159b3361Sopenharmony_ci}
1288159b3361Sopenharmony_ci
1289159b3361Sopenharmony_civoid ACM::BuildBitrateTable()
1290159b3361Sopenharmony_ci{
1291159b3361Sopenharmony_ci	my_debug.OutPut("entering BuildBitrateTable");
1292159b3361Sopenharmony_ci
1293159b3361Sopenharmony_ci	// fill the table
1294159b3361Sopenharmony_ci	unsigned int channel,bitrate,freq;
1295159b3361Sopenharmony_ci
1296159b3361Sopenharmony_ci	bitrate_table.clear();
1297159b3361Sopenharmony_ci
1298159b3361Sopenharmony_ci	// CBR bitrates
1299159b3361Sopenharmony_ci	for (channel = 0;channel < SIZE_CHANNEL_MODE;channel++)
1300159b3361Sopenharmony_ci	{
1301159b3361Sopenharmony_ci		// MPEG I
1302159b3361Sopenharmony_ci		for (freq = 0;freq < SIZE_FREQ_MPEG1;freq++)
1303159b3361Sopenharmony_ci		{
1304159b3361Sopenharmony_ci			for (bitrate = 0;bitrate < SIZE_BITRATE_MPEG1;bitrate++)
1305159b3361Sopenharmony_ci			{
1306159b3361Sopenharmony_ci
1307159b3361Sopenharmony_ci				if (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg1_freq[freq], mpeg1_bitrate[bitrate], channel+1))
1308159b3361Sopenharmony_ci				{
1309159b3361Sopenharmony_ci					bitrate_item bitrate_table_tmp;
1310159b3361Sopenharmony_ci
1311159b3361Sopenharmony_ci					bitrate_table_tmp.frequency = mpeg1_freq[freq];
1312159b3361Sopenharmony_ci					bitrate_table_tmp.bitrate = mpeg1_bitrate[bitrate];
1313159b3361Sopenharmony_ci					bitrate_table_tmp.channels = channel+1;
1314159b3361Sopenharmony_ci					bitrate_table_tmp.mode = vbr_off;
1315159b3361Sopenharmony_ci					bitrate_table.push_back(bitrate_table_tmp);
1316159b3361Sopenharmony_ci				}
1317159b3361Sopenharmony_ci			}
1318159b3361Sopenharmony_ci		}
1319159b3361Sopenharmony_ci		// MPEG II / II.5
1320159b3361Sopenharmony_ci		for (freq = 0;freq < SIZE_FREQ_MPEG2;freq++)
1321159b3361Sopenharmony_ci		{
1322159b3361Sopenharmony_ci			for (bitrate = 0;bitrate < SIZE_BITRATE_MPEG2;bitrate++)
1323159b3361Sopenharmony_ci			{
1324159b3361Sopenharmony_ci				if (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg2_freq[freq], mpeg2_bitrate[bitrate], channel+1))
1325159b3361Sopenharmony_ci				{
1326159b3361Sopenharmony_ci					bitrate_item bitrate_table_tmp;
1327159b3361Sopenharmony_ci
1328159b3361Sopenharmony_ci                                        bitrate_table_tmp.frequency = mpeg2_freq[freq];
1329159b3361Sopenharmony_ci					bitrate_table_tmp.bitrate = mpeg2_bitrate[bitrate];
1330159b3361Sopenharmony_ci					bitrate_table_tmp.channels = channel+1;
1331159b3361Sopenharmony_ci					bitrate_table_tmp.mode = vbr_abr;
1332159b3361Sopenharmony_ci					bitrate_table.push_back(bitrate_table_tmp);
1333159b3361Sopenharmony_ci				}
1334159b3361Sopenharmony_ci			}
1335159b3361Sopenharmony_ci		}
1336159b3361Sopenharmony_ci	}
1337159b3361Sopenharmony_ci
1338159b3361Sopenharmony_ci	if (my_EncodingProperties.GetAbrOutputMode())
1339159b3361Sopenharmony_ci	// ABR bitrates
1340159b3361Sopenharmony_ci	{
1341159b3361Sopenharmony_ci		for (channel = 0;channel < SIZE_CHANNEL_MODE;channel++)
1342159b3361Sopenharmony_ci		{
1343159b3361Sopenharmony_ci			// MPEG I
1344159b3361Sopenharmony_ci			for (freq = 0;freq < SIZE_FREQ_MPEG1;freq++)
1345159b3361Sopenharmony_ci			{
1346159b3361Sopenharmony_ci				for (bitrate = my_EncodingProperties.GetAbrBitrateMax();
1347159b3361Sopenharmony_ci					   bitrate >= my_EncodingProperties.GetAbrBitrateMin();
1348159b3361Sopenharmony_ci				     bitrate -= my_EncodingProperties.GetAbrBitrateStep())
1349159b3361Sopenharmony_ci				{
1350159b3361Sopenharmony_ci					if (bitrate >= mpeg1_bitrate[SIZE_BITRATE_MPEG1-1] && (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg1_freq[freq], bitrate, channel+1)))
1351159b3361Sopenharmony_ci					{
1352159b3361Sopenharmony_ci						bitrate_item bitrate_table_tmp;
1353159b3361Sopenharmony_ci
1354159b3361Sopenharmony_ci						bitrate_table_tmp.frequency = mpeg1_freq[freq];
1355159b3361Sopenharmony_ci						bitrate_table_tmp.bitrate = bitrate;
1356159b3361Sopenharmony_ci						bitrate_table_tmp.channels = channel+1;
1357159b3361Sopenharmony_ci						bitrate_table_tmp.mode = vbr_abr;
1358159b3361Sopenharmony_ci						bitrate_table.push_back(bitrate_table_tmp);
1359159b3361Sopenharmony_ci					}
1360159b3361Sopenharmony_ci				}
1361159b3361Sopenharmony_ci			}
1362159b3361Sopenharmony_ci			// MPEG II / II.5
1363159b3361Sopenharmony_ci			for (freq = 0;freq < SIZE_FREQ_MPEG2;freq++)
1364159b3361Sopenharmony_ci			{
1365159b3361Sopenharmony_ci				for (bitrate = my_EncodingProperties.GetAbrBitrateMax();
1366159b3361Sopenharmony_ci					   bitrate >= my_EncodingProperties.GetAbrBitrateMin();
1367159b3361Sopenharmony_ci				     bitrate -= my_EncodingProperties.GetAbrBitrateStep())
1368159b3361Sopenharmony_ci				{
1369159b3361Sopenharmony_ci					if (bitrate >= mpeg2_bitrate[SIZE_BITRATE_MPEG2-1] && (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg2_freq[freq], bitrate, channel+1)))
1370159b3361Sopenharmony_ci					{
1371159b3361Sopenharmony_ci						bitrate_item bitrate_table_tmp;
1372159b3361Sopenharmony_ci
1373159b3361Sopenharmony_ci						bitrate_table_tmp.frequency = mpeg2_freq[freq];
1374159b3361Sopenharmony_ci						bitrate_table_tmp.bitrate = bitrate;
1375159b3361Sopenharmony_ci						bitrate_table_tmp.channels = channel+1;
1376159b3361Sopenharmony_ci						bitrate_table_tmp.mode = vbr_abr;
1377159b3361Sopenharmony_ci						bitrate_table.push_back(bitrate_table_tmp);
1378159b3361Sopenharmony_ci					}
1379159b3361Sopenharmony_ci				}
1380159b3361Sopenharmony_ci			}
1381159b3361Sopenharmony_ci		}
1382159b3361Sopenharmony_ci	}
1383159b3361Sopenharmony_ci
1384159b3361Sopenharmony_ci	// sorting by frequency/bitrate/channel
1385159b3361Sopenharmony_ci	std::sort(bitrate_table.begin(), bitrate_table.end());
1386159b3361Sopenharmony_ci
1387159b3361Sopenharmony_ci/*	{
1388159b3361Sopenharmony_ci		// display test
1389159b3361Sopenharmony_ci		int i=0;
1390159b3361Sopenharmony_ci		for (i=0; i<bitrate_table.size();i++)
1391159b3361Sopenharmony_ci		{
1392159b3361Sopenharmony_ci			my_debug.OutPut("bitrate_table[%d].frequency = %d",i,bitrate_table[i].frequency);
1393159b3361Sopenharmony_ci			my_debug.OutPut("bitrate_table[%d].bitrate = %d",i,bitrate_table[i].bitrate);
1394159b3361Sopenharmony_ci			my_debug.OutPut("bitrate_table[%d].channel = %d",i,bitrate_table[i].channels);
1395159b3361Sopenharmony_ci			my_debug.OutPut("bitrate_table[%d].ABR = %s\n",i,(bitrate_table[i].mode == vbr_abr)?"ABR":"CBR");
1396159b3361Sopenharmony_ci		}
1397159b3361Sopenharmony_ci	}*/
1398159b3361Sopenharmony_ci
1399159b3361Sopenharmony_ci	my_debug.OutPut("leaving BuildBitrateTable");
1400159b3361Sopenharmony_ci}
1401