ACM.cpp 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405
  1. /**
  2. *
  3. * Lame ACM wrapper, encode/decode MP3 based RIFF/AVI files in MS Windows
  4. *
  5. * Copyright (c) 2002 Steve Lhomme <steve.lhomme at free.fr>
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. */
  22. /*!
  23. \author Steve Lhomme
  24. \version \$Id$
  25. */
  26. #if !defined(STRICT)
  27. #define STRICT
  28. #endif // STRICT
  29. #include <algorithm>
  30. #include <windows.h>
  31. #include <windowsx.h>
  32. #include <intshcut.h>
  33. #include <mmreg.h>
  34. #include <msacm.h>
  35. #include <msacmdrv.h>
  36. #include <assert.h>
  37. #include <lame.h>
  38. #include "adebug.h"
  39. #include "resource.h"
  40. #include "ACMStream.h"
  41. #ifdef ENABLE_DECODING
  42. #include "DecodeStream.h"
  43. #endif // ENABLE_DECODING
  44. #include "ACM.h"
  45. #ifndef IDC_HAND
  46. #define IDC_HAND MAKEINTRESOURCE(32649)
  47. #endif // IDC_HAND
  48. char ACM::VersionString[120];
  49. const char ACM_VERSION[] = "0.9.2";
  50. #ifdef WIN32
  51. //
  52. // 32-bit versions
  53. //
  54. #if (WINVER >= 0x0400)
  55. #define VERSION_ACM_DRIVER MAKE_ACM_VERSION(4, 0, 0)
  56. #else
  57. #define VERSION_ACM_DRIVER MAKE_ACM_VERSION(3, 51, 0)
  58. #endif
  59. #define VERSION_MSACM MAKE_ACM_VERSION(3, 50, 0)
  60. #else
  61. //
  62. // 16-bit versions
  63. //
  64. #define VERSION_ACM_DRIVER MAKE_ACM_VERSION(1, 0, 0)
  65. #define VERSION_MSACM MAKE_ACM_VERSION(2, 1, 0)
  66. #endif
  67. #define PERSONAL_FORMAT WAVE_FORMAT_MPEGLAYER3
  68. #define SIZE_FORMAT_STRUCT sizeof(MPEGLAYER3WAVEFORMAT)
  69. //#define SIZE_FORMAT_STRUCT 0
  70. //static const char channel_mode[][13] = {"mono","stereo","joint stereo","dual channel"};
  71. static const char channel_mode[][13] = {"mono","stereo"};
  72. static const unsigned int mpeg1_freq[] = {48000,44100,32000};
  73. static const unsigned int mpeg2_freq[] = {24000,22050,16000,12000,11025,8000};
  74. static const unsigned int mpeg1_bitrate[] = {320, 256, 224, 192, 160, 128, 112, 96, 80, 64, 56, 48, 40, 32};
  75. static const unsigned int mpeg2_bitrate[] = {160, 144, 128, 112, 96, 80, 64, 56, 48, 40, 32, 24, 16, 8};
  76. #define SIZE_CHANNEL_MODE (sizeof(channel_mode) / (sizeof(char) * 13))
  77. #define SIZE_FREQ_MPEG1 (sizeof(mpeg1_freq) / sizeof(unsigned int))
  78. #define SIZE_FREQ_MPEG2 (sizeof(mpeg2_freq) / sizeof(unsigned int))
  79. #define SIZE_BITRATE_MPEG1 (sizeof(mpeg1_bitrate) / sizeof(unsigned int))
  80. #define SIZE_BITRATE_MPEG2 (sizeof(mpeg2_bitrate) / sizeof(unsigned int))
  81. static const int FORMAT_TAG_MAX_NB = 2; // PCM and PERSONAL (mandatory to have at least PCM and your format)
  82. static const int FILTER_TAG_MAX_NB = 0; // this is a codec, not a filter
  83. // number of supported PCM formats
  84. static const int FORMAT_MAX_NB_PCM =
  85. 2 * // number of PCM channel mode (stereo/mono)
  86. (SIZE_FREQ_MPEG1 + // number of MPEG 1 sampling freq
  87. SIZE_FREQ_MPEG2); // number of MPEG 2 sampling freq
  88. //////////////////////////////////////////////////////////////////////
  89. //
  90. //////////////////////////////////////////////////////////////////////
  91. bool bitrate_item::operator<(const bitrate_item & other_bitrate) const
  92. {
  93. return (other_bitrate.frequency < frequency ||
  94. (other_bitrate.frequency == frequency &&
  95. (other_bitrate.bitrate < bitrate ||
  96. (other_bitrate.bitrate == bitrate &&
  97. (other_bitrate.channels < channels)))));
  98. }
  99. //////////////////////////////////////////////////////////////////////
  100. // Configuration Dialog
  101. //////////////////////////////////////////////////////////////////////
  102. /*
  103. static CALLBACK ConfigProc(
  104. HWND hwndDlg, // handle to dialog box
  105. UINT uMsg, // message
  106. WPARAM wParam, // first message parameter
  107. LPARAM lParam // second message parameter
  108. )
  109. {
  110. BOOL bResult;
  111. switch (uMsg) {
  112. case WM_COMMAND:
  113. UINT command;
  114. command = GET_WM_COMMAND_ID(wParam, lParam);
  115. if (IDOK == command)
  116. {
  117. EndDialog(hwndDlg, (IDOK == command));
  118. } else if (IDCANCEL == command)
  119. {
  120. EndDialog(hwndDlg, (IDOK == command));
  121. }
  122. bResult = FALSE;
  123. break;
  124. default:
  125. bResult = FALSE; // will be treated by DefWindowProc
  126. }
  127. return bResult;
  128. }
  129. inline DWORD ACM::Configure(HWND hParentWindow, LPDRVCONFIGINFO pConfig)
  130. {
  131. my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "ACM : Configure (Parent Window = 0x%08X)",hParentWindow);
  132. DialogBoxParam( my_hModule, MAKEINTRESOURCE(IDD_CONFIG), hParentWindow, ::ConfigProc , (LPARAM)this);
  133. return DRVCNF_OK; // Can also return
  134. // DRVCNF_CANCEL
  135. // and DRVCNF_RESTART
  136. }
  137. */
  138. //////////////////////////////////////////////////////////////////////
  139. // About Dialog
  140. //////////////////////////////////////////////////////////////////////
  141. static BOOL CALLBACK AboutProc(
  142. HWND hwndDlg, // handle to dialog box
  143. UINT uMsg, // message
  144. WPARAM wParam, // first message parameter
  145. LPARAM lParam // second message parameter
  146. )
  147. {
  148. static HBRUSH hBrushStatic = NULL;
  149. // static LOGFONT lf; // structure for font information
  150. // static HFONT hfnt;
  151. static HCURSOR hcOverCursor = NULL;
  152. BOOL bResult;
  153. switch (uMsg) {
  154. case WM_INITDIALOG:
  155. char tmp[150];
  156. wsprintf(tmp,"LAME MP3 codec v%s", ACM::GetVersionString());
  157. ::SetWindowText(GetDlgItem( hwndDlg, IDC_STATIC_ABOUT_TITLE), tmp);
  158. /*
  159. ::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
  160. lf.lfUnderline = TRUE;
  161. hfnt = ::CreateFontIndirect(&lf);
  162. ::SendMessage(::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL), WM_SETFONT, (WPARAM) hfnt, TRUE);
  163. * /
  164. hBrushStatic = ::CreateSolidBrush(::GetSysColor (COLOR_BTNFACE));
  165. */ hcOverCursor = ::LoadCursor(NULL,(LPCTSTR)IDC_HAND);
  166. if (hcOverCursor == NULL)
  167. hcOverCursor = ::LoadCursor(NULL,(LPCTSTR)IDC_CROSS);
  168. bResult = TRUE;
  169. break;
  170. /*
  171. case WM_CTLCOLORSTATIC:
  172. /// \todo only if there are URLs
  173. if ((HWND)lParam == ::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL))
  174. {
  175. ::SetTextColor((HDC)wParam, ::GetSysColor (COLOR_HIGHLIGHT));
  176. ::SetBkColor((HDC)wParam, ::GetSysColor (COLOR_BTNFACE));
  177. return (LRESULT) hBrushStatic;
  178. }
  179. else
  180. return (LRESULT) NULL;
  181. */
  182. case WM_MOUSEMOVE:
  183. {
  184. POINT pnt;
  185. ::GetCursorPos(&pnt);
  186. RECT rect;
  187. ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL), &rect);
  188. if ( ::PtInRect(&rect,pnt) )
  189. {
  190. ::SetCursor(hcOverCursor);
  191. }
  192. }
  193. break;
  194. case WM_LBUTTONUP:
  195. {
  196. POINT pnt;
  197. ::GetCursorPos(&pnt);
  198. RECT rect;
  199. ::GetWindowRect( ::GetDlgItem(hwndDlg,IDC_STATIC_ABOUT_URL), &rect);
  200. TCHAR Url[200];
  201. bool bUrl = false;
  202. if (::PtInRect(&rect,pnt))
  203. {
  204. wsprintf(Url,get_lame_url());
  205. bUrl = true;
  206. }
  207. if (bUrl)
  208. {
  209. LPSTR tmpStr;
  210. HRESULT hresult = ::TranslateURL(Url, TRANSLATEURL_FL_GUESS_PROTOCOL|TRANSLATEURL_FL_GUESS_PROTOCOL, &tmpStr);
  211. if (hresult == S_OK)
  212. ::ShellExecute(hwndDlg,"open",tmpStr,NULL,"",SW_SHOWMAXIMIZED );
  213. else if (hresult == S_FALSE)
  214. ::ShellExecute(hwndDlg,"open",Url,NULL,"",SW_SHOWMAXIMIZED );
  215. }
  216. }
  217. break;
  218. case WM_COMMAND:
  219. UINT command;
  220. command = GET_WM_COMMAND_ID(wParam, lParam);
  221. if (IDOK == command)
  222. {
  223. EndDialog(hwndDlg, TRUE);
  224. }
  225. bResult = FALSE;
  226. break;
  227. case IDC_STATIC_ABOUT_URL:
  228. break;
  229. default:
  230. bResult = FALSE; // will be treated by DefWindowProc
  231. }
  232. return bResult;
  233. }
  234. inline DWORD ACM::About(HWND hParentWindow)
  235. {
  236. my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "ACM : About (Parent Window = 0x%08X)",hParentWindow);
  237. DialogBoxParam( my_hModule, MAKEINTRESOURCE(IDD_ABOUT), hParentWindow, ::AboutProc , (LPARAM)this);
  238. return DRVCNF_OK; // Can also return
  239. // DRVCNF_CANCEL
  240. // and DRVCNF_RESTART
  241. }
  242. //////////////////////////////////////////////////////////////////////
  243. // Construction/Destruction
  244. //////////////////////////////////////////////////////////////////////
  245. ACM::ACM( HMODULE hModule )
  246. :my_hModule(hModule),
  247. my_hIcon(NULL),
  248. my_debug(ADbg(DEBUG_LEVEL_CREATION)),
  249. my_EncodingProperties(hModule)
  250. {
  251. my_EncodingProperties.ParamsRestore();
  252. /// \todo get the debug level from the registry
  253. unsigned char DebugFileName[512];
  254. char tmp[128];
  255. wsprintf(tmp,"LAMEacm 0x%08X",this);
  256. my_debug.setPrefix(tmp); /// \todo get it from the registry
  257. my_debug.setIncludeTime(true); /// \todo get it from the registry
  258. // Check in the registry if we have to Output Debug information
  259. DebugFileName[0] = '\0';
  260. HKEY OssKey;
  261. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\MUKOLI", 0, KEY_READ , &OssKey ) == ERROR_SUCCESS) {
  262. DWORD DataType;
  263. DWORD DebugFileNameSize = 512;
  264. if (RegQueryValueEx( OssKey, "DebugFile", NULL, &DataType, DebugFileName, &DebugFileNameSize ) == ERROR_SUCCESS) {
  265. if (DataType == REG_SZ) {
  266. my_debug.setUseFile(true);
  267. my_debug.setDebugFile((char *)DebugFileName);
  268. my_debug.OutPut("Debug file is %s",(char *)DebugFileName);
  269. }
  270. }
  271. }
  272. wsprintf(VersionString,"%s - %s", ACM_VERSION, get_lame_version() );
  273. BuildBitrateTable();
  274. my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "New ACM Creation (0x%08X)",this);
  275. }
  276. ACM::~ACM()
  277. {
  278. // not used, it's done automatically when closing the driver if (my_hIcon != NULL)
  279. // CloseHandle(my_hIcon);
  280. bitrate_table.clear();
  281. my_debug.OutPut(DEBUG_LEVEL_FUNC_START, "ACM Deleted (0x%08X)",this);
  282. }
  283. //////////////////////////////////////////////////////////////////////
  284. // Main message handler
  285. //////////////////////////////////////////////////////////////////////
  286. LONG ACM::DriverProcedure(const HDRVR hdrvr, const UINT msg, LONG lParam1, LONG lParam2)
  287. {
  288. DWORD dwRes = 0L;
  289. //my_debug.OutPut(DEBUG_LEVEL_MSG, "message 0x%08X for ThisACM 0x%08X", msg, this);
  290. switch (msg) {
  291. case DRV_INSTALL:
  292. my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_INSTALL");
  293. // Sent when the driver is installed.
  294. dwRes = DRVCNF_OK; // Can also return
  295. break; // DRVCNF_CANCEL
  296. // and DRV_RESTART
  297. case DRV_REMOVE:
  298. // Sent when the driver is removed.
  299. my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_REMOVE");
  300. dwRes = 1L; // return value ignored
  301. break;
  302. case DRV_QUERYCONFIGURE:
  303. my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_QUERYCONFIGURE");
  304. // Sent to determine if the driver can be
  305. // configured.
  306. dwRes = 1L; // Zero indicates configuration
  307. break; // NOT supported
  308. case DRV_CONFIGURE:
  309. my_debug.OutPut(DEBUG_LEVEL_MSG, "DRV_CONFIGURE");
  310. // Sent to display the configuration
  311. // dialog box for the driver.
  312. // dwRes = Configure( (HWND) lParam1, (LPDRVCONFIGINFO) lParam2 );
  313. if (my_EncodingProperties.Config(my_hModule, (HWND) lParam1))
  314. {
  315. dwRes = DRVCNF_OK; // Can also return
  316. // DRVCNF_CANCEL
  317. // and DRVCNF_RESTART
  318. } else {
  319. dwRes = DRVCNF_CANCEL;
  320. }
  321. break;
  322. /**************************************
  323. // ACM additional messages
  324. ***************************************/
  325. case ACMDM_DRIVER_ABOUT:
  326. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_DRIVER_ABOUT");
  327. dwRes = About( (HWND) lParam1 );
  328. break;
  329. case ACMDM_DRIVER_DETAILS: // acmDriverDetails
  330. // Fill-in general informations about the driver/codec
  331. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_DRIVER_DETAILS");
  332. dwRes = OnDriverDetails(hdrvr, (LPACMDRIVERDETAILS) lParam1);
  333. break;
  334. case ACMDM_FORMATTAG_DETAILS: // acmFormatTagDetails
  335. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_FORMATTAG_DETAILS");
  336. dwRes = OnFormatTagDetails((LPACMFORMATTAGDETAILS) lParam1, lParam2);
  337. break;
  338. case ACMDM_FORMAT_DETAILS: // acmFormatDetails
  339. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_FORMAT_DETAILS");
  340. dwRes = OnFormatDetails((LPACMFORMATDETAILS) lParam1, lParam2);
  341. break;
  342. case ACMDM_FORMAT_SUGGEST: // acmFormatSuggest
  343. // Sent to determine if the driver can be
  344. // configured.
  345. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_FORMAT_SUGGEST");
  346. dwRes = OnFormatSuggest((LPACMDRVFORMATSUGGEST) lParam1);
  347. break;
  348. /**************************************
  349. // ACM stream messages
  350. ***************************************/
  351. case ACMDM_STREAM_OPEN:
  352. // Sent to determine if the driver can be
  353. // configured.
  354. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_OPEN");
  355. dwRes = OnStreamOpen((LPACMDRVSTREAMINSTANCE) lParam1);
  356. break;
  357. case ACMDM_STREAM_SIZE:
  358. // returns a recommended size for a source
  359. // or destination buffer on an ACM stream
  360. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_SIZE");
  361. dwRes = OnStreamSize((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMSIZE)lParam2);
  362. break;
  363. case ACMDM_STREAM_PREPARE:
  364. // prepares an ACMSTREAMHEADER structure for
  365. // an ACM stream conversion
  366. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_PREPARE");
  367. dwRes = OnStreamPrepareHeader((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMSTREAMHEADER) lParam2);
  368. break;
  369. case ACMDM_STREAM_UNPREPARE:
  370. // cleans up the preparation performed by
  371. // the ACMDM_STREAM_PREPARE message for an ACM stream
  372. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_UNPREPARE");
  373. dwRes = OnStreamUnPrepareHeader((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMSTREAMHEADER) lParam2);
  374. break;
  375. case ACMDM_STREAM_CONVERT:
  376. // perform a conversion on the specified conversion stream
  377. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_CONVERT");
  378. dwRes = OnStreamConvert((LPACMDRVSTREAMINSTANCE)lParam1, (LPACMDRVSTREAMHEADER) lParam2);
  379. break;
  380. case ACMDM_STREAM_CLOSE:
  381. // closes an ACM conversion stream
  382. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACMDM_STREAM_CLOSE");
  383. dwRes = OnStreamClose((LPACMDRVSTREAMINSTANCE)lParam1);
  384. break;
  385. /**************************************
  386. // Unknown message
  387. ***************************************/
  388. default:
  389. // Process any other messages.
  390. my_debug.OutPut(DEBUG_LEVEL_MSG, "ACM::DriverProc unknown message (0x%08X), lParam1 = 0x%08X, lParam2 = 0x%08X", msg, lParam1, lParam2);
  391. return DefDriverProc ((DWORD)this, hdrvr, msg, lParam1, lParam2);
  392. }
  393. return dwRes;
  394. }
  395. //////////////////////////////////////////////////////////////////////
  396. // Special message handlers
  397. //////////////////////////////////////////////////////////////////////
  398. /*!
  399. Retreive the config details of this ACM driver
  400. The index represent the specified format
  401. \param a_FormatDetails will be filled with all the corresponding data
  402. */
  403. inline DWORD ACM::OnFormatDetails(LPACMFORMATDETAILS a_FormatDetails, const LPARAM a_Query)
  404. {
  405. DWORD Result = ACMERR_NOTPOSSIBLE;
  406. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATDETAILS a_Query = 0x%08X",a_Query);
  407. switch (a_Query & ACM_FORMATDETAILSF_QUERYMASK) {
  408. // Fill-in the informations corresponding to the FormatDetails->dwFormatTagIndex
  409. case ACM_FORMATDETAILSF_INDEX :
  410. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "enter ACM_FORMATDETAILSF_INDEX for index 0x%04X:%03d",a_FormatDetails->dwFormatTag,a_FormatDetails->dwFormatIndex);
  411. if (a_FormatDetails->dwFormatTag == PERSONAL_FORMAT) {
  412. if (a_FormatDetails->dwFormatIndex < GetNumberEncodingFormats()) {
  413. LPWAVEFORMATEX WaveExt;
  414. WaveExt = a_FormatDetails->pwfx;
  415. WaveExt->wFormatTag = PERSONAL_FORMAT;
  416. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format in : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
  417. GetMP3FormatForIndex(a_FormatDetails->dwFormatIndex, *WaveExt, a_FormatDetails->szFormat);
  418. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format out : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
  419. Result = MMSYSERR_NOERROR;
  420. }
  421. else
  422. {
  423. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATDETAILSF_INDEX unknown index 0x%04X:%03d",a_FormatDetails->dwFormatTag,a_FormatDetails->dwFormatIndex);
  424. }
  425. }
  426. else if (a_FormatDetails->dwFormatTag == WAVE_FORMAT_PCM) {
  427. if (a_FormatDetails->dwFormatIndex < FORMAT_MAX_NB_PCM) {
  428. LPWAVEFORMATEX WaveExt;
  429. WaveExt = a_FormatDetails->pwfx;
  430. WaveExt->wFormatTag = WAVE_FORMAT_PCM;
  431. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format in : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
  432. GetPCMFormatForIndex(a_FormatDetails->dwFormatIndex, *WaveExt, a_FormatDetails->szFormat);
  433. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "format out : channels %d, sample rate %d", WaveExt->nChannels, WaveExt->nSamplesPerSec);
  434. Result = MMSYSERR_NOERROR;
  435. }
  436. else
  437. {
  438. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATDETAILSF_INDEX unknown index 0x%04X:%03d",a_FormatDetails->dwFormatTag,a_FormatDetails->dwFormatIndex);
  439. }
  440. }
  441. else
  442. {
  443. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Unknown a_FormatDetails->dwFormatTag = 0x%08X",a_FormatDetails->dwFormatTag);
  444. }
  445. case ACM_FORMATDETAILSF_FORMAT :
  446. /// \todo we may output the corresponding strong (only for personal format)
  447. LPWAVEFORMATEX WaveExt;
  448. WaveExt = a_FormatDetails->pwfx;
  449. 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);
  450. Result = MMSYSERR_NOERROR;
  451. break;
  452. default:
  453. Result = ACMERR_NOTPOSSIBLE;
  454. break;
  455. }
  456. a_FormatDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  457. return Result;
  458. }
  459. /*!
  460. Retreive the details of each known format by this ACM driver
  461. The index represent the specified format (0 = MP3 / 1 = PCM)
  462. \param a_FormatTagDetails will be filled with all the corresponding data
  463. */
  464. inline DWORD ACM::OnFormatTagDetails(LPACMFORMATTAGDETAILS a_FormatTagDetails, const LPARAM a_Query)
  465. {
  466. DWORD Result;
  467. DWORD the_format = WAVE_FORMAT_UNKNOWN; // the format to give details
  468. if (a_FormatTagDetails->cbStruct >= sizeof(*a_FormatTagDetails)) {
  469. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACMDM_FORMATTAG_DETAILS, a_Query = 0x%08X",a_Query);
  470. switch(a_Query & ACM_FORMATTAGDETAILSF_QUERYMASK) {
  471. case ACM_FORMATTAGDETAILSF_INDEX:
  472. // Fill-in the informations corresponding to the a_FormatDetails->dwFormatTagIndex
  473. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "get ACM_FORMATTAGDETAILSF_INDEX for index %03d",a_FormatTagDetails->dwFormatTagIndex);
  474. if (a_FormatTagDetails->dwFormatTagIndex < FORMAT_TAG_MAX_NB) {
  475. switch (a_FormatTagDetails->dwFormatTagIndex)
  476. {
  477. case 0:
  478. the_format = PERSONAL_FORMAT;
  479. break;
  480. default :
  481. the_format = WAVE_FORMAT_PCM;
  482. break;
  483. }
  484. }
  485. else
  486. {
  487. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATTAGDETAILSF_INDEX for unsupported index %03d",a_FormatTagDetails->dwFormatTagIndex);
  488. Result = ACMERR_NOTPOSSIBLE;
  489. }
  490. break;
  491. case ACM_FORMATTAGDETAILSF_FORMATTAG:
  492. // Fill-in the informations corresponding to the a_FormatDetails->dwFormatTagIndex and hdrvr given
  493. switch (a_FormatTagDetails->dwFormatTag)
  494. {
  495. case WAVE_FORMAT_PCM:
  496. the_format = WAVE_FORMAT_PCM;
  497. break;
  498. case PERSONAL_FORMAT:
  499. the_format = PERSONAL_FORMAT;
  500. break;
  501. default:
  502. return (ACMERR_NOTPOSSIBLE);
  503. }
  504. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "get ACM_FORMATTAGDETAILSF_FORMATTAG for index 0x%02X, cStandardFormats = %d",a_FormatTagDetails->dwFormatTagIndex,a_FormatTagDetails->cStandardFormats);
  505. break;
  506. case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
  507. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "ACM_FORMATTAGDETAILSF_LARGESTSIZE not used");
  508. Result = 0L;
  509. break;
  510. default:
  511. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails Unknown Format tag query");
  512. Result = MMSYSERR_NOTSUPPORTED;
  513. break;
  514. }
  515. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails the_format = 0x%08X",the_format);
  516. switch(the_format)
  517. {
  518. case WAVE_FORMAT_PCM:
  519. a_FormatTagDetails->dwFormatTag = WAVE_FORMAT_PCM;
  520. a_FormatTagDetails->dwFormatTagIndex = 0;
  521. a_FormatTagDetails->cbFormatSize = sizeof(PCMWAVEFORMAT);
  522. /// \note 0 may mean we don't know how to decode
  523. a_FormatTagDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  524. a_FormatTagDetails->cStandardFormats = FORMAT_MAX_NB_PCM;
  525. // should be filled by Windows a_FormatTagDetails->szFormatTag[0] = '\0';
  526. Result = MMSYSERR_NOERROR;
  527. break;
  528. case PERSONAL_FORMAT:
  529. a_FormatTagDetails->dwFormatTag = PERSONAL_FORMAT;
  530. a_FormatTagDetails->dwFormatTagIndex = 1;
  531. a_FormatTagDetails->cbFormatSize = SIZE_FORMAT_STRUCT;
  532. a_FormatTagDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  533. a_FormatTagDetails->cStandardFormats = GetNumberEncodingFormats();
  534. lstrcpyW( a_FormatTagDetails->szFormatTag, L"Lame MP3" );
  535. Result = MMSYSERR_NOERROR;
  536. break;
  537. default:
  538. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails Unknown format 0x%08X",the_format);
  539. return (ACMERR_NOTPOSSIBLE);
  540. }
  541. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnFormatTagDetails %d possibilities for format 0x%08X",a_FormatTagDetails->cStandardFormats,the_format);
  542. }
  543. else
  544. {
  545. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "a_FormatTagDetails->cbStruct < sizeof(*a_FormatDetails)");
  546. Result = ACMERR_NOTPOSSIBLE;
  547. }
  548. return Result;
  549. }
  550. /*!
  551. Retreive the global details of this ACM driver
  552. \param a_DriverDetail will be filled with all the corresponding data
  553. */
  554. inline DWORD ACM::OnDriverDetails(const HDRVR hdrvr, LPACMDRIVERDETAILS a_DriverDetail)
  555. {
  556. if (my_hIcon == NULL)
  557. my_hIcon = LoadIcon(GetDriverModuleHandle(hdrvr), MAKEINTRESOURCE(IDI_ICON));
  558. a_DriverDetail->hicon = my_hIcon;
  559. a_DriverDetail->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
  560. a_DriverDetail->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
  561. /// \note this is an explicit hack of the FhG values
  562. /// \note later it could be a new value when the decoding is done
  563. a_DriverDetail->wMid = MM_FRAUNHOFER_IIS;
  564. a_DriverDetail->wPid = MM_FHGIIS_MPEGLAYER3;
  565. a_DriverDetail->vdwACM = VERSION_MSACM;
  566. a_DriverDetail->vdwDriver = VERSION_ACM_DRIVER;
  567. a_DriverDetail->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
  568. a_DriverDetail->cFormatTags = FORMAT_TAG_MAX_NB; // 2 : MP3 and PCM
  569. // a_DriverDetail->cFormatTags = 1; // 2 : MP3 and PCM
  570. a_DriverDetail->cFilterTags = FILTER_TAG_MAX_NB;
  571. lstrcpyW( a_DriverDetail->szShortName, L"LAME MP3" );
  572. char tmpStr[128];
  573. wsprintf(tmpStr, "LAME MP3 Codec v%s", GetVersionString());
  574. int u = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, tmpStr, -1, a_DriverDetail->szLongName, 0);
  575. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, tmpStr, -1, a_DriverDetail->szLongName, u);
  576. lstrcpyW( a_DriverDetail->szCopyright, L"2002 Steve Lhomme" );
  577. lstrcpyW( a_DriverDetail->szLicensing, L"LGPL (see gnu.org)" );
  578. /// \todo update this part when the code changes
  579. lstrcpyW( a_DriverDetail->szFeatures , L"only CBR implementation" );
  580. return MMSYSERR_NOERROR; // Can also return DRVCNF_CANCEL
  581. }
  582. /*!
  583. Suggest an output format for the specified input format
  584. \param a_FormatSuggest will be filled with all the corresponding data
  585. */
  586. inline DWORD ACM::OnFormatSuggest(LPACMDRVFORMATSUGGEST a_FormatSuggest)
  587. {
  588. DWORD Result = MMSYSERR_NOTSUPPORTED;
  589. DWORD fdwSuggest = (ACM_FORMATSUGGESTF_TYPEMASK & a_FormatSuggest->fdwSuggest);
  590. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest %s%s%s%s (0x%08X)",
  591. (fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS) ? "channels, ":"",
  592. (fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC) ? "samples/sec, ":"",
  593. (fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE) ? "bits/sample, ":"",
  594. (fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) ? "format, ":"",
  595. fdwSuggest);
  596. my_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",
  597. a_FormatSuggest->pwfxSrc->wFormatTag,
  598. a_FormatSuggest->pwfxSrc->nChannels,
  599. a_FormatSuggest->pwfxSrc->nSamplesPerSec,
  600. a_FormatSuggest->pwfxSrc->nAvgBytesPerSec,
  601. a_FormatSuggest->pwfxSrc->nBlockAlign,
  602. a_FormatSuggest->pwfxSrc->wBitsPerSample);
  603. 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",
  604. a_FormatSuggest->pwfxDst->wFormatTag,
  605. a_FormatSuggest->pwfxDst->nChannels,
  606. a_FormatSuggest->pwfxDst->nSamplesPerSec,
  607. a_FormatSuggest->pwfxDst->nAvgBytesPerSec,
  608. a_FormatSuggest->pwfxDst->nBlockAlign,
  609. a_FormatSuggest->pwfxDst->wBitsPerSample);
  610. switch (a_FormatSuggest->pwfxSrc->wFormatTag)
  611. {
  612. case WAVE_FORMAT_PCM:
  613. /// \todo handle here the decoding ?
  614. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest for PCM source");
  615. //
  616. // if the destination format tag is restricted, verify that
  617. // it is within our capabilities...
  618. //
  619. // this driver is able to decode to PCM
  620. //
  621. if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
  622. {
  623. if (PERSONAL_FORMAT != a_FormatSuggest->pwfxDst->wFormatTag)
  624. return (ACMERR_NOTPOSSIBLE);
  625. }
  626. else
  627. {
  628. a_FormatSuggest->pwfxDst->wFormatTag = PERSONAL_FORMAT;
  629. }
  630. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed A");
  631. //
  632. // if the destination channel count is restricted, verify that
  633. // it is within our capabilities...
  634. //
  635. // this driver is not able to change the number of channels
  636. //
  637. if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
  638. {
  639. if (a_FormatSuggest->pwfxSrc->nChannels != a_FormatSuggest->pwfxDst->nChannels)
  640. return (ACMERR_NOTPOSSIBLE);
  641. }
  642. else
  643. {
  644. a_FormatSuggest->pwfxDst->nChannels = a_FormatSuggest->pwfxSrc->nChannels;
  645. }
  646. if (a_FormatSuggest->pwfxSrc->nChannels != 1 && a_FormatSuggest->pwfxSrc->nChannels != 2)
  647. return MMSYSERR_INVALPARAM;
  648. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed B");
  649. //
  650. // if the destination samples per second is restricted, verify
  651. // that it is within our capabilities...
  652. //
  653. // this driver is not able to change the sample rate
  654. //
  655. if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
  656. {
  657. if (a_FormatSuggest->pwfxSrc->nSamplesPerSec != a_FormatSuggest->pwfxDst->nSamplesPerSec)
  658. return (ACMERR_NOTPOSSIBLE);
  659. }
  660. else
  661. {
  662. a_FormatSuggest->pwfxDst->nSamplesPerSec = a_FormatSuggest->pwfxSrc->nSamplesPerSec;
  663. }
  664. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed C");
  665. //
  666. // if the destination bits per sample is restricted, verify
  667. // that it is within our capabilities...
  668. //
  669. // We prefer decoding to 16-bit PCM.
  670. //
  671. if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
  672. {
  673. if ( (16 != a_FormatSuggest->pwfxDst->wBitsPerSample) && (8 != a_FormatSuggest->pwfxDst->wBitsPerSample) )
  674. return (ACMERR_NOTPOSSIBLE);
  675. }
  676. else
  677. {
  678. a_FormatSuggest->pwfxDst->wBitsPerSample = 16;
  679. }
  680. // a_FormatSuggest->pwfxDst->nBlockAlign = FORMAT_BLOCK_ALIGN;
  681. a_FormatSuggest->pwfxDst->nBlockAlign = a_FormatSuggest->pwfxDst->nChannels * a_FormatSuggest->pwfxDst->wBitsPerSample / 8;
  682. a_FormatSuggest->pwfxDst->nAvgBytesPerSec = a_FormatSuggest->pwfxDst->nChannels * 64000 / 8;
  683. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed");
  684. Result = MMSYSERR_NOERROR;
  685. break;
  686. case PERSONAL_FORMAT:
  687. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest for PERSONAL source");
  688. //
  689. // if the destination format tag is restricted, verify that
  690. // it is within our capabilities...
  691. //
  692. // this driver is able to decode to PCM
  693. //
  694. if (ACM_FORMATSUGGESTF_WFORMATTAG & fdwSuggest)
  695. {
  696. if (WAVE_FORMAT_PCM != a_FormatSuggest->pwfxDst->wFormatTag)
  697. return (ACMERR_NOTPOSSIBLE);
  698. }
  699. else
  700. {
  701. a_FormatSuggest->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
  702. }
  703. //
  704. // if the destination channel count is restricted, verify that
  705. // it is within our capabilities...
  706. //
  707. // this driver is not able to change the number of channels
  708. //
  709. if (ACM_FORMATSUGGESTF_NCHANNELS & fdwSuggest)
  710. {
  711. if (a_FormatSuggest->pwfxSrc->nChannels != a_FormatSuggest->pwfxDst->nChannels)
  712. return (ACMERR_NOTPOSSIBLE);
  713. }
  714. else
  715. {
  716. a_FormatSuggest->pwfxDst->nChannels = a_FormatSuggest->pwfxSrc->nChannels;
  717. }
  718. //
  719. // if the destination samples per second is restricted, verify
  720. // that it is within our capabilities...
  721. //
  722. // this driver is not able to change the sample rate
  723. //
  724. if (ACM_FORMATSUGGESTF_NSAMPLESPERSEC & fdwSuggest)
  725. {
  726. if (a_FormatSuggest->pwfxSrc->nSamplesPerSec != a_FormatSuggest->pwfxDst->nSamplesPerSec)
  727. return (ACMERR_NOTPOSSIBLE);
  728. }
  729. else
  730. {
  731. a_FormatSuggest->pwfxDst->nSamplesPerSec = a_FormatSuggest->pwfxSrc->nSamplesPerSec;
  732. }
  733. //
  734. // if the destination bits per sample is restricted, verify
  735. // that it is within our capabilities...
  736. //
  737. // We prefer decoding to 16-bit PCM.
  738. //
  739. if (ACM_FORMATSUGGESTF_WBITSPERSAMPLE & fdwSuggest)
  740. {
  741. if ( (16 != a_FormatSuggest->pwfxDst->wBitsPerSample) && (8 != a_FormatSuggest->pwfxDst->wBitsPerSample) )
  742. return (ACMERR_NOTPOSSIBLE);
  743. }
  744. else
  745. {
  746. a_FormatSuggest->pwfxDst->wBitsPerSample = 16;
  747. }
  748. // a_FormatSuggest->pwfxDst->nBlockAlign = FORMAT_BLOCK_ALIGN;
  749. a_FormatSuggest->pwfxDst->nBlockAlign = a_FormatSuggest->pwfxDst->nChannels * a_FormatSuggest->pwfxDst->wBitsPerSample / 8;
  750. /// \todo this value must be a correct one !
  751. a_FormatSuggest->pwfxDst->nAvgBytesPerSec = a_FormatSuggest->pwfxDst->nSamplesPerSec * a_FormatSuggest->pwfxDst->nChannels * a_FormatSuggest->pwfxDst->wBitsPerSample / 8;
  752. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Suggest succeed");
  753. Result = MMSYSERR_NOERROR;
  754. break;
  755. }
  756. 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",
  757. a_FormatSuggest->pwfxDst->wFormatTag,
  758. a_FormatSuggest->pwfxDst->nChannels,
  759. a_FormatSuggest->pwfxDst->nSamplesPerSec,
  760. a_FormatSuggest->pwfxDst->nAvgBytesPerSec,
  761. a_FormatSuggest->pwfxDst->nBlockAlign,
  762. a_FormatSuggest->pwfxDst->wBitsPerSample);
  763. return Result;
  764. }
  765. /*!
  766. Create a stream instance for decoding/encoding
  767. \param a_StreamInstance contain information about the stream desired
  768. */
  769. inline DWORD ACM::OnStreamOpen(LPACMDRVSTREAMINSTANCE a_StreamInstance)
  770. {
  771. DWORD Result = ACMERR_NOTPOSSIBLE;
  772. //
  773. // the most important condition to check before doing anything else
  774. // is that this ACM driver can actually perform the conversion we are
  775. // being opened for. this check should fail as quickly as possible
  776. // if the conversion is not possible by this driver.
  777. //
  778. // it is VERY important to fail quickly so the ACM can attempt to
  779. // find a driver that is suitable for the conversion. also note that
  780. // the ACM may call this driver several times with slightly different
  781. // format specifications before giving up.
  782. //
  783. // this driver first verifies that the source and destination formats
  784. // are acceptable...
  785. //
  786. switch (a_StreamInstance->pwfxSrc->wFormatTag)
  787. {
  788. case WAVE_FORMAT_PCM:
  789. 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);
  790. if (a_StreamInstance->pwfxDst->wFormatTag == PERSONAL_FORMAT)
  791. {
  792. unsigned int OutputFrequency;
  793. /// \todo Smart mode
  794. if (my_EncodingProperties.GetSmartOutputMode())
  795. OutputFrequency = ACMStream::GetOutputSampleRate(a_StreamInstance->pwfxSrc->nSamplesPerSec,a_StreamInstance->pwfxDst->nAvgBytesPerSec,a_StreamInstance->pwfxDst->nChannels);
  796. else
  797. OutputFrequency = a_StreamInstance->pwfxSrc->nSamplesPerSec;
  798. 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);
  799. /// \todo add the possibility to have channel resampling (mono to stereo / stereo to mono)
  800. /// \todo support resampling ?
  801. /// \todo only do the test on OutputFrequency in "Smart Output" mode
  802. if (a_StreamInstance->pwfxDst->nSamplesPerSec != OutputFrequency ||
  803. // a_StreamInstance->pwfxSrc->nSamplesPerSec != a_StreamInstance->pwfxDst->nSamplesPerSec ||
  804. a_StreamInstance->pwfxSrc->nChannels != a_StreamInstance->pwfxDst->nChannels ||
  805. a_StreamInstance->pwfxSrc->wBitsPerSample != 16)
  806. {
  807. Result = ACMERR_NOTPOSSIBLE;
  808. } else {
  809. if ((a_StreamInstance->fdwOpen & ACM_STREAMOPENF_QUERY) == 0)
  810. {
  811. ACMStream * the_stream = ACMStream::Create();
  812. a_StreamInstance->dwInstance = (DWORD) the_stream;
  813. if (the_stream != NULL)
  814. {
  815. MPEGLAYER3WAVEFORMAT * casted = (MPEGLAYER3WAVEFORMAT *) a_StreamInstance->pwfxDst;
  816. vbr_mode a_mode = (casted->fdwFlags-2 == 0)?vbr_abr:vbr_off;
  817. if (the_stream->init(a_StreamInstance->pwfxDst->nSamplesPerSec,
  818. OutputFrequency,
  819. a_StreamInstance->pwfxDst->nChannels,
  820. a_StreamInstance->pwfxDst->nAvgBytesPerSec,
  821. a_mode))
  822. Result = MMSYSERR_NOERROR;
  823. else
  824. ACMStream::Erase( the_stream );
  825. }
  826. }
  827. else
  828. {
  829. Result = MMSYSERR_NOERROR;
  830. }
  831. }
  832. }
  833. break;
  834. case PERSONAL_FORMAT:
  835. 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);
  836. if (a_StreamInstance->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
  837. {
  838. #ifdef ENABLE_DECODING
  839. if ((a_StreamInstance->fdwOpen & ACM_STREAMOPENF_QUERY) == 0)
  840. {
  841. /// \todo create the decoding stream
  842. 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);
  843. DecodeStream * the_stream = DecodeStream::Create();
  844. a_StreamInstance->dwInstance = (DWORD) the_stream;
  845. if (the_stream != NULL)
  846. {
  847. if (the_stream->init(a_StreamInstance->pwfxDst->nSamplesPerSec,
  848. a_StreamInstance->pwfxDst->nChannels,
  849. a_StreamInstance->pwfxDst->nAvgBytesPerSec,
  850. a_StreamInstance->pwfxSrc->nAvgBytesPerSec))
  851. Result = MMSYSERR_NOERROR;
  852. else
  853. DecodeStream::Erase( the_stream );
  854. }
  855. }
  856. else
  857. {
  858. /// \todo decoding verification
  859. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream is valid");
  860. Result = MMSYSERR_NOERROR;
  861. }
  862. #endif // ENABLE_DECODING
  863. }
  864. break;
  865. }
  866. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Open stream Result = %d",Result);
  867. return Result;
  868. }
  869. inline DWORD ACM::OnStreamSize(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMDRVSTREAMSIZE the_StreamSize)
  870. {
  871. DWORD Result = ACMERR_NOTPOSSIBLE;
  872. switch (ACM_STREAMSIZEF_QUERYMASK & the_StreamSize->fdwSize)
  873. {
  874. case ACM_STREAMSIZEF_DESTINATION:
  875. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Get source buffer size for destination size = %d",the_StreamSize->cbDstLength);
  876. break;
  877. case ACM_STREAMSIZEF_SOURCE:
  878. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "Get destination buffer size for source size = %d",the_StreamSize->cbSrcLength);
  879. if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
  880. PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
  881. {
  882. ACMStream * the_stream = (ACMStream *) a_StreamInstance->dwInstance;
  883. if (the_stream != NULL)
  884. {
  885. the_StreamSize->cbDstLength = the_stream->GetOutputSizeForInput(the_StreamSize->cbSrcLength);
  886. Result = MMSYSERR_NOERROR;
  887. }
  888. }
  889. else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
  890. WAVE_FORMAT_PCM== a_StreamInstance->pwfxDst->wFormatTag)
  891. {
  892. #ifdef ENABLE_DECODING
  893. DecodeStream * the_stream = (DecodeStream *) a_StreamInstance->dwInstance;
  894. if (the_stream != NULL)
  895. {
  896. the_StreamSize->cbDstLength = the_stream->GetOutputSizeForInput(the_StreamSize->cbSrcLength);
  897. Result = MMSYSERR_NOERROR;
  898. }
  899. #endif // ENABLE_DECODING
  900. }
  901. break;
  902. default:
  903. Result = MMSYSERR_INVALFLAG;
  904. break;
  905. }
  906. return Result;
  907. }
  908. inline DWORD ACM::OnStreamClose(LPACMDRVSTREAMINSTANCE a_StreamInstance)
  909. {
  910. DWORD Result = ACMERR_NOTPOSSIBLE;
  911. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamClose the stream 0x%X",a_StreamInstance->dwInstance);
  912. if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
  913. PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
  914. {
  915. ACMStream::Erase( (ACMStream *) a_StreamInstance->dwInstance );
  916. }
  917. else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
  918. WAVE_FORMAT_PCM== a_StreamInstance->pwfxDst->wFormatTag)
  919. {
  920. #ifdef ENABLE_DECODING
  921. DecodeStream::Erase( (DecodeStream *) a_StreamInstance->dwInstance );
  922. #endif // ENABLE_DECODING
  923. }
  924. // nothing to do yet
  925. Result = MMSYSERR_NOERROR;
  926. return Result;
  927. }
  928. inline DWORD ACM::OnStreamPrepareHeader(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMSTREAMHEADER a_StreamHeader)
  929. {
  930. DWORD Result = ACMERR_NOTPOSSIBLE;
  931. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, " prepare : Src : %d (0x%08X) / %d - Dst : %d (0x%08X) / %d"
  932. , a_StreamHeader->cbSrcLength
  933. , a_StreamHeader->pbSrc
  934. , a_StreamHeader->cbSrcLengthUsed
  935. , a_StreamHeader->cbDstLength
  936. , a_StreamHeader->pbDst
  937. , a_StreamHeader->cbDstLengthUsed
  938. );
  939. if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
  940. PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
  941. {
  942. ACMStream * the_stream = (ACMStream *)a_StreamInstance->dwInstance;
  943. if (the_stream->open(my_EncodingProperties))
  944. Result = MMSYSERR_NOERROR;
  945. }
  946. else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
  947. WAVE_FORMAT_PCM == a_StreamInstance->pwfxDst->wFormatTag)
  948. {
  949. #ifdef ENABLE_DECODING
  950. DecodeStream * the_stream = (DecodeStream *)a_StreamInstance->dwInstance;
  951. if (the_stream->open())
  952. Result = MMSYSERR_NOERROR;
  953. #endif // ENABLE_DECODING
  954. }
  955. return Result;
  956. }
  957. inline DWORD ACM::OnStreamUnPrepareHeader(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMSTREAMHEADER a_StreamHeader)
  958. {
  959. DWORD Result = ACMERR_NOTPOSSIBLE;
  960. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "unprepare : Src : %d / %d - Dst : %d / %d"
  961. , a_StreamHeader->cbSrcLength
  962. , a_StreamHeader->cbSrcLengthUsed
  963. , a_StreamHeader->cbDstLength
  964. , a_StreamHeader->cbDstLengthUsed
  965. );
  966. if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
  967. PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
  968. {
  969. ACMStream * the_stream = (ACMStream *)a_StreamInstance->dwInstance;
  970. DWORD OutputSize = a_StreamHeader->cbDstLength;
  971. if (the_stream->close(a_StreamHeader->pbDst, &OutputSize) && (OutputSize <= a_StreamHeader->cbDstLength))
  972. {
  973. a_StreamHeader->cbDstLengthUsed = OutputSize;
  974. Result = MMSYSERR_NOERROR;
  975. }
  976. }
  977. else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
  978. WAVE_FORMAT_PCM== a_StreamInstance->pwfxDst->wFormatTag)
  979. {
  980. #ifdef ENABLE_DECODING
  981. DecodeStream * the_stream = (DecodeStream *)a_StreamInstance->dwInstance;
  982. DWORD OutputSize = a_StreamHeader->cbDstLength;
  983. if (the_stream->close(a_StreamHeader->pbDst, &OutputSize) && (OutputSize <= a_StreamHeader->cbDstLength))
  984. {
  985. a_StreamHeader->cbDstLengthUsed = OutputSize;
  986. Result = MMSYSERR_NOERROR;
  987. }
  988. #endif // ENABLE_DECODING
  989. }
  990. return Result;
  991. }
  992. inline DWORD ACM::OnStreamConvert(LPACMDRVSTREAMINSTANCE a_StreamInstance, LPACMDRVSTREAMHEADER a_StreamHeader)
  993. {
  994. DWORD Result = ACMERR_NOTPOSSIBLE;
  995. if (WAVE_FORMAT_PCM == a_StreamInstance->pwfxSrc->wFormatTag &&
  996. PERSONAL_FORMAT == a_StreamInstance->pwfxDst->wFormatTag)
  997. {
  998. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamConvert SRC = PCM (encode)");
  999. ACMStream * the_stream = (ACMStream *) a_StreamInstance->dwInstance;
  1000. if (the_stream != NULL)
  1001. {
  1002. if (the_stream->ConvertBuffer( a_StreamHeader ))
  1003. Result = MMSYSERR_NOERROR;
  1004. }
  1005. }
  1006. else if (PERSONAL_FORMAT == a_StreamInstance->pwfxSrc->wFormatTag &&
  1007. WAVE_FORMAT_PCM == a_StreamInstance->pwfxDst->wFormatTag)
  1008. {
  1009. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamConvert SRC = MP3 (decode)");
  1010. #ifdef ENABLE_DECODING
  1011. DecodeStream * the_stream = (DecodeStream *) a_StreamInstance->dwInstance;
  1012. if (the_stream != NULL)
  1013. {
  1014. if (the_stream->ConvertBuffer( a_StreamHeader ))
  1015. Result = MMSYSERR_NOERROR;
  1016. }
  1017. #endif // ENABLE_DECODING
  1018. }
  1019. else
  1020. my_debug.OutPut(DEBUG_LEVEL_FUNC_CODE, "OnStreamConvert unsupported conversion");
  1021. return Result;
  1022. }
  1023. void ACM::GetMP3FormatForIndex(const DWORD the_Index, WAVEFORMATEX & the_Format, unsigned short the_String[ACMFORMATDETAILS_FORMAT_CHARS]) const
  1024. {
  1025. int Block_size;
  1026. char temp[ACMFORMATDETAILS_FORMAT_CHARS];
  1027. if (the_Index < bitrate_table.size())
  1028. {
  1029. // the_Format.wBitsPerSample = 16;
  1030. the_Format.wBitsPerSample = 0;
  1031. /// \todo handle more channel modes (mono, stereo, joint-stereo, dual-channel)
  1032. // the_Format.nChannels = SIZE_CHANNEL_MODE - int(the_Index % SIZE_CHANNEL_MODE);
  1033. the_Format.nBlockAlign = 1;
  1034. the_Format.nSamplesPerSec = bitrate_table[the_Index].frequency;
  1035. the_Format.nAvgBytesPerSec = bitrate_table[the_Index].bitrate * 1000 / 8;
  1036. if (bitrate_table[the_Index].frequency >= mpeg1_freq[SIZE_FREQ_MPEG1-1])
  1037. Block_size = 1152;
  1038. else
  1039. Block_size = 576;
  1040. the_Format.nChannels = bitrate_table[the_Index].channels;
  1041. the_Format.cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
  1042. MPEGLAYER3WAVEFORMAT * tmpFormat = (MPEGLAYER3WAVEFORMAT *) &the_Format;
  1043. tmpFormat->wID = 1;
  1044. // this is the only way I found to know if we do CBR or ABR
  1045. tmpFormat->fdwFlags = 2 + ((bitrate_table[the_Index].mode == vbr_abr)?0:2);
  1046. tmpFormat->nBlockSize = Block_size * the_Format.nAvgBytesPerSec / the_Format.nSamplesPerSec;
  1047. tmpFormat->nFramesPerBlock = 1;
  1048. tmpFormat->nCodecDelay = 0; // 0x0571 on FHG
  1049. /// \todo : generate the string with the appropriate stereo mode
  1050. if (bitrate_table[the_Index].mode == vbr_abr)
  1051. wsprintfA( temp, "%d Hz, %d kbps ABR, %s", the_Format.nSamplesPerSec, the_Format.nAvgBytesPerSec * 8 / 1000, (the_Format.nChannels == 1)?"Mono":"Stereo");
  1052. else
  1053. wsprintfA( temp, "%d Hz, %d kbps CBR, %s", the_Format.nSamplesPerSec, the_Format.nAvgBytesPerSec * 8 / 1000, (the_Format.nChannels == 1)?"Mono":"Stereo");
  1054. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, temp, -1, the_String, ACMFORMATDETAILS_FORMAT_CHARS);
  1055. }
  1056. }
  1057. void ACM::GetPCMFormatForIndex(const DWORD the_Index, WAVEFORMATEX & the_Format, unsigned short the_String[ACMFORMATDETAILS_FORMAT_CHARS]) const
  1058. {
  1059. the_Format.nChannels = SIZE_CHANNEL_MODE - int(the_Index % SIZE_CHANNEL_MODE);
  1060. the_Format.wBitsPerSample = 16;
  1061. the_Format.nBlockAlign = the_Format.nChannels * the_Format.wBitsPerSample / 8;
  1062. DWORD a_Channel_Independent = the_Index / SIZE_CHANNEL_MODE;
  1063. // first MPEG1 frequencies
  1064. if (a_Channel_Independent < SIZE_FREQ_MPEG1)
  1065. {
  1066. the_Format.nSamplesPerSec = mpeg1_freq[a_Channel_Independent];
  1067. }
  1068. else
  1069. {
  1070. a_Channel_Independent -= SIZE_FREQ_MPEG1;
  1071. the_Format.nSamplesPerSec = mpeg2_freq[a_Channel_Independent];
  1072. }
  1073. the_Format.nAvgBytesPerSec = the_Format.nSamplesPerSec * the_Format.nChannels * the_Format.wBitsPerSample / 8;
  1074. }
  1075. DWORD ACM::GetNumberEncodingFormats() const
  1076. {
  1077. return bitrate_table.size();
  1078. }
  1079. bool ACM::IsSmartOutput(const int frequency, const int bitrate, const int channels) const
  1080. {
  1081. double compression_ratio = double(frequency * 2 * channels) / double(bitrate * 100);
  1082. //my_debug.OutPut(DEBUG_LEVEL_FUNC_DEBUG, "compression_ratio %f, freq %d, bitrate %d, channels %d", compression_ratio, frequency, bitrate, channels);
  1083. if(my_EncodingProperties.GetSmartOutputMode())
  1084. return (compression_ratio <= my_EncodingProperties.GetSmartRatio());
  1085. else return true;
  1086. }
  1087. void ACM::BuildBitrateTable()
  1088. {
  1089. my_debug.OutPut("entering BuildBitrateTable");
  1090. // fill the table
  1091. unsigned int channel,bitrate,freq;
  1092. bitrate_table.clear();
  1093. // CBR bitrates
  1094. for (channel = 0;channel < SIZE_CHANNEL_MODE;channel++)
  1095. {
  1096. // MPEG I
  1097. for (freq = 0;freq < SIZE_FREQ_MPEG1;freq++)
  1098. {
  1099. for (bitrate = 0;bitrate < SIZE_BITRATE_MPEG1;bitrate++)
  1100. {
  1101. if (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg1_freq[freq], mpeg1_bitrate[bitrate], channel+1))
  1102. {
  1103. bitrate_item bitrate_table_tmp;
  1104. bitrate_table_tmp.frequency = mpeg1_freq[freq];
  1105. bitrate_table_tmp.bitrate = mpeg1_bitrate[bitrate];
  1106. bitrate_table_tmp.channels = channel+1;
  1107. bitrate_table_tmp.mode = vbr_off;
  1108. bitrate_table.push_back(bitrate_table_tmp);
  1109. }
  1110. }
  1111. }
  1112. // MPEG II / II.5
  1113. for (freq = 0;freq < SIZE_FREQ_MPEG2;freq++)
  1114. {
  1115. for (bitrate = 0;bitrate < SIZE_BITRATE_MPEG2;bitrate++)
  1116. {
  1117. if (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg2_freq[freq], mpeg2_bitrate[bitrate], channel+1))
  1118. {
  1119. bitrate_item bitrate_table_tmp;
  1120. bitrate_table_tmp.frequency = mpeg2_freq[freq];
  1121. bitrate_table_tmp.bitrate = mpeg2_bitrate[bitrate];
  1122. bitrate_table_tmp.channels = channel+1;
  1123. bitrate_table_tmp.mode = vbr_abr;
  1124. bitrate_table.push_back(bitrate_table_tmp);
  1125. }
  1126. }
  1127. }
  1128. }
  1129. if (my_EncodingProperties.GetAbrOutputMode())
  1130. // ABR bitrates
  1131. {
  1132. for (channel = 0;channel < SIZE_CHANNEL_MODE;channel++)
  1133. {
  1134. // MPEG I
  1135. for (freq = 0;freq < SIZE_FREQ_MPEG1;freq++)
  1136. {
  1137. for (bitrate = my_EncodingProperties.GetAbrBitrateMax();
  1138. bitrate >= my_EncodingProperties.GetAbrBitrateMin();
  1139. bitrate -= my_EncodingProperties.GetAbrBitrateStep())
  1140. {
  1141. if (bitrate >= mpeg1_bitrate[SIZE_BITRATE_MPEG1-1] && (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg1_freq[freq], bitrate, channel+1)))
  1142. {
  1143. bitrate_item bitrate_table_tmp;
  1144. bitrate_table_tmp.frequency = mpeg1_freq[freq];
  1145. bitrate_table_tmp.bitrate = bitrate;
  1146. bitrate_table_tmp.channels = channel+1;
  1147. bitrate_table_tmp.mode = vbr_abr;
  1148. bitrate_table.push_back(bitrate_table_tmp);
  1149. }
  1150. }
  1151. }
  1152. // MPEG II / II.5
  1153. for (freq = 0;freq < SIZE_FREQ_MPEG2;freq++)
  1154. {
  1155. for (bitrate = my_EncodingProperties.GetAbrBitrateMax();
  1156. bitrate >= my_EncodingProperties.GetAbrBitrateMin();
  1157. bitrate -= my_EncodingProperties.GetAbrBitrateStep())
  1158. {
  1159. if (bitrate >= mpeg2_bitrate[SIZE_BITRATE_MPEG2-1] && (!my_EncodingProperties.GetSmartOutputMode() || IsSmartOutput(mpeg2_freq[freq], bitrate, channel+1)))
  1160. {
  1161. bitrate_item bitrate_table_tmp;
  1162. bitrate_table_tmp.frequency = mpeg2_freq[freq];
  1163. bitrate_table_tmp.bitrate = bitrate;
  1164. bitrate_table_tmp.channels = channel+1;
  1165. bitrate_table_tmp.mode = vbr_abr;
  1166. bitrate_table.push_back(bitrate_table_tmp);
  1167. }
  1168. }
  1169. }
  1170. }
  1171. }
  1172. // sorting by frequency/bitrate/channel
  1173. std::sort(bitrate_table.begin(), bitrate_table.end());
  1174. /* {
  1175. // display test
  1176. int i=0;
  1177. for (i=0; i<bitrate_table.size();i++)
  1178. {
  1179. my_debug.OutPut("bitrate_table[%d].frequency = %d",i,bitrate_table[i].frequency);
  1180. my_debug.OutPut("bitrate_table[%d].bitrate = %d",i,bitrate_table[i].bitrate);
  1181. my_debug.OutPut("bitrate_table[%d].channel = %d",i,bitrate_table[i].channels);
  1182. my_debug.OutPut("bitrate_table[%d].ABR = %s\n",i,(bitrate_table[i].mode == vbr_abr)?"ABR":"CBR");
  1183. }
  1184. }*/
  1185. my_debug.OutPut("leaving BuildBitrateTable");
  1186. }