shithub: aacenc

Download patch

ref: b5b96c5825881e9e1203cc6a2aaf83bac4a2109d
parent: 58547908ce3d5c6f0b79153d015cc6f699f6eb30
author: menno <menno>
date: Thu Jan 17 07:22:44 EST 2002

AAC ACM codec

--- /dev/null
+++ b/plugins/aac_acm/StdAfx.cpp
@@ -1,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+//	aac_acm.pch will be the pre-compiled header
+//	stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
--- /dev/null
+++ b/plugins/aac_acm/StdAfx.h
@@ -1,0 +1,24 @@
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__4B6551ED_F548_4AD7_B0DA_37308A3D8313__INCLUDED_)
+#define AFX_STDAFX_H__4B6551ED_F548_4AD7_B0DA_37308A3D8313__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+// Insert your headers here
+#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
+
+#include <windows.h>
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__4B6551ED_F548_4AD7_B0DA_37308A3D8313__INCLUDED_)
--- /dev/null
+++ b/plugins/aac_acm/aac_acm.cpp
@@ -1,0 +1,192 @@
+// aac_acm.cpp : Defines the entry point for the DLL application.
+//
+
+#include "stdafx.h"
+#include "codec.h"
+#include <list>
+
+struct messagetype
+{
+    const char* c;
+    int i;
+};
+
+const messagetype g_types[] =
+{
+	"DRV_LOAD", DRV_LOAD,
+	"DRV_FREE", DRV_FREE,
+	"DRV_OPEN", DRV_OPEN,
+	"DRV_CLOSE", DRV_CLOSE,
+	"DRV_DISABLE", DRV_DISABLE,
+	"DRV_ENABLE", DRV_ENABLE,
+	"DRV_INSTALL", DRV_INSTALL,
+	"DRV_REMOVE", DRV_REMOVE,
+	"DRV_CONFIGURE", DRV_CONFIGURE,
+	"DRV_QUERYCONFIGURE", DRV_QUERYCONFIGURE,
+	"ACMDM_DRIVER_DETAILS", ACMDM_DRIVER_DETAILS,
+	"ACMDM_DRIVER_ABOUT", ACMDM_DRIVER_ABOUT,
+	"ACMDM_FORMATTAG_DETAILS", ACMDM_FORMATTAG_DETAILS,
+	"ACMDM_FORMAT_DETAILS", ACMDM_FORMAT_DETAILS,
+	"ACMDM_FORMAT_SUGGEST", ACMDM_FORMAT_SUGGEST,
+	"ACMDM_STREAM_OPEN", ACMDM_STREAM_OPEN,
+	"ACMDM_STREAM_CLOSE", ACMDM_STREAM_CLOSE,
+	"ACMDM_STREAM_SIZE", ACMDM_STREAM_SIZE,
+	"ACMDM_STREAM_CONVERT", ACMDM_STREAM_CONVERT,
+	"ACMDM_STREAM_RESET", ACMDM_STREAM_RESET,
+	"ACMDM_STREAM_PREPARE", ACMDM_STREAM_PREPARE,
+	"ACMDM_STREAM_UNPREPARE", ACMDM_STREAM_UNPREPARE,
+	"ACMDM_STREAM_UPDATE", ACMDM_STREAM_UPDATE,
+};
+
+#include <stdio.h>
+
+static void Message(const char* fmt, ...)
+{
+#ifndef NDEBUG
+	FILE* f=fopen("c:\\msg.log", "ab");
+	va_list va;
+	va_start(va, fmt);
+	vfprintf(f, fmt, va);
+	va_end(va);
+	fclose(f);
+#endif
+}
+
+//codec c1;
+//codec c2;
+//int iCodecs=0;
+
+bool g_bAttached=false;
+std::list<codec*> g_codec_objects;
+
+BOOL APIENTRY DllMain( HANDLE hModule, 
+					  DWORD  ul_reason_for_call, 
+					  LPVOID lpReserved
+					  )
+{
+    Message("DllMain(%d)\n");
+    if(ul_reason_for_call==DLL_PROCESS_ATTACH)
+		g_bAttached=true;
+    if(ul_reason_for_call==DLL_PROCESS_DETACH)
+    {
+		for(std::list<codec*>::iterator it=g_codec_objects.begin();
+		it!=g_codec_objects.end();
+		it++)
+			delete *it;
+		g_bAttached=false;
+    }
+    return TRUE;
+}
+
+
+extern "C" LONG WINAPI DriverProc(DWORD dwDriverID, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2) 
+{
+    codec *cdx = (codec *)(UINT)dwDriverID;
+    ICOPEN *icinfo = (ICOPEN *)lParam2;
+	
+    if(g_bAttached==false) 
+		// it really happens!
+		// and since our heap may be already destroyed, we don't dare to do anything
+		return E_FAIL;
+	
+    for(int i=0; i<sizeof(g_types)/sizeof(g_types[0]); i++)
+    {
+		if(uiMessage==g_types[i].i)
+		{
+			Message("%x %s %x %x\n", dwDriverID, g_types[i].c, lParam1, lParam2);
+			goto cont;
+		}
+    }
+    Message("%x %x %x %x\n", dwDriverID, uiMessage, lParam1, lParam2);
+cont:
+    switch (uiMessage) 
+    {
+    /****************************************
+	
+	  standard driver messages
+	  
+	****************************************/
+		
+    case DRV_LOAD:
+		return (LRESULT)1L;
+		
+    case DRV_FREE:
+		return (LRESULT)1L;
+		
+    case DRV_OPEN:
+		if (icinfo && icinfo->fccType != ICTYPE_AUDIO) return NULL;
+		//	if(!iCodecs)
+		//	    cdx=&c1;
+		//	else
+		//	    cdx=&c2;
+		//	iCodecs++;
+		cdx = new codec;
+		g_codec_objects.push_back(cdx);
+		if (icinfo) icinfo->dwError = cdx ? ICERR_OK : ICERR_MEMORY;
+		Message(" ==> %x\n", cdx);
+		return (LRESULT)(DWORD)(UINT) cdx;
+		
+    case DRV_CLOSE:
+		g_codec_objects.remove(cdx);
+		delete cdx;
+		return (LRESULT)1L;
+		
+    case DRV_DISABLE:
+    case DRV_ENABLE:
+		return (LRESULT)1L;
+		
+    case DRV_INSTALL:
+    case DRV_REMOVE:
+		return (LRESULT)DRV_OK;
+		
+    case DRV_QUERYCONFIGURE:    
+		return (LRESULT)0L; // does support drive configure with the about box
+		
+    case DRV_CONFIGURE:
+		//	return cdx->about(lParam1,lParam2);
+		MessageBox(0, "Configure", "qqq", MB_OK);
+		return DRVCNF_OK;
+		
+    case ACMDM_DRIVER_DETAILS:
+		return cdx->details((ACMDRIVERDETAILSW*)lParam1);
+		
+    case ACMDM_DRIVER_ABOUT:
+		return cdx->about((DWORD)lParam1);
+		
+    case ACMDM_FORMATTAG_DETAILS:
+		return cdx->formattag_details((ACMFORMATTAGDETAILSW*)lParam1, (DWORD)lParam2);
+		
+    case ACMDM_FORMAT_DETAILS:
+		return cdx->format_details((ACMFORMATDETAILSW*)lParam1, (DWORD)lParam2);
+		
+    case ACMDM_FORMAT_SUGGEST:
+		return cdx->format_suggest((ACMDRVFORMATSUGGEST*)lParam1);
+		
+    case ACMDM_STREAM_OPEN:
+		return cdx->open((ACMDRVSTREAMINSTANCE*)lParam1);
+		
+    case ACMDM_STREAM_PREPARE:
+		return cdx->prepare((ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*) lParam2);
+		
+    case ACMDM_STREAM_RESET:
+		return cdx->reset((ACMDRVSTREAMINSTANCE*)lParam1);
+		
+    case ACMDM_STREAM_SIZE:
+		return cdx->size((ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMSIZE*)lParam2);
+		
+    case ACMDM_STREAM_UNPREPARE:
+		return cdx->unprepare((ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*) lParam2);
+		
+    case ACMDM_STREAM_CONVERT:
+		return cdx->convert((ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*) lParam2);
+		
+    case ACMDM_STREAM_CLOSE:
+		return cdx->close((ACMDRVSTREAMINSTANCE*)lParam1);
+		
+    }
+	
+    if (uiMessage < DRV_USER)
+		return DefDriverProc(dwDriverID, hDriver, uiMessage, lParam1, lParam2);
+    else
+        return MMSYSERR_NOTSUPPORTED;
+}
--- /dev/null
+++ b/plugins/aac_acm/aac_acm.def
@@ -1,0 +1,5 @@
+LIBRARY      "aac_acm"
+DESCRIPTION  'Windows Dynamic Link Library'
+
+EXPORTS
+	DriverProc PRIVATE
--- /dev/null
+++ b/plugins/aac_acm/aac_acm.dsp
@@ -1,0 +1,140 @@
+# Microsoft Developer Studio Project File - Name="aac_acm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=aac_acm - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "aac_acm.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "aac_acm.mak" CFG="aac_acm - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "aac_acm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "aac_acm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=xicl6.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "aac_acm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "../../include" /I "../../../faad/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "NDEBUG"
+# ADD RSC /l 0x419 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=xilink6.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib vfw32.lib winmm.lib /nologo /subsystem:windows /dll /machine:I386 /libpath:"bin"
+
+!ELSEIF  "$(CFG)" == "aac_acm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../include" /I "../../../faad/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /FA<none>
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x419 /d "_DEBUG"
+# ADD RSC /l 0x419 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=xilink6.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib vfw32.lib winmm.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept /libpath:"bin"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "aac_acm - Win32 Release"
+# Name "aac_acm - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\aac_acm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\aac_acm.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\codec.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\codec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\include\faac.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\faad\include\faad.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\msacmdrv.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/plugins/aac_acm/aac_acm.dsw
@@ -1,0 +1,59 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "aac_acm"=.\aac_acm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name libfaac
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name libfaad
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libfaac"=..\..\libfaac\libfaac.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libfaad"=..\..\..\faad\libfaad\libfaad.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+++ b/plugins/aac_acm/aac_acm.inf
@@ -1,0 +1,80 @@
+
+
+[Version]
+Signature = "$CHICAGO$"
+Class = MEDIA
+
+[SourceDisksNames]
+1="AAC Audio Codec Install Disk",, 0001
+
+[SourceDisksFiles]
+aac_acm.dll=1
+aac_acm.inf=1
+
+[Installable.Drivers]
+divxa32 = 1:aac_acm.dll, "msacm.aac" , "AAC Audio Codec" , , , 
+
+[DefaultInstall]
+CopyFiles=AAC.Copy,AAC.Copy.Inf
+Updateinis = AAC.Updateini
+addreg = AAC.AddReg9x
+MediaType = SOFTWARE
+
+[DefaultInstall.ntx86]
+CopyFiles=AAC.Copy,AAC.Copy.Inf
+addreg = AAC.AddRegNT
+MediaType = SOFTWARE
+
+[Remove_AAC]
+AddReg = AAC.Unregister
+DelFiles = AAC.Copy,AAC.Copy.Inf
+UpdateInis = AAC.DelIni
+
+[AAC.Copy]
+aac_acm.dll
+
+[AAC.Copy.Inf]
+aac_acm.inf
+
+[AAC.UpdateIni]
+system.ini, drivers32,,"msacm.aac=aac_acm.dll"
+
+[AAC.DelIni]
+system.ini, drivers32,"msacm.aac=aac_acm.dll"
+
+[AAC.AddReg9x]
+HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\acm\msacm.aac,Description,,%AACAudio%
+HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\acm\msacm.aac,Driver,,aac_acm.dll
+HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\acm\msacm.aac,FriendlyName,,%AACAudio%
+
+HKLM,%UnInstallPath%,DisplayName,,%UninstallDispName%
+HKLM,%UnInstallPath%,UninstallString,,"%10%\rundll.exe setupx.dll,InstallHinfSection Remove_AAC 132 %17%\%InfFile%"
+
+[AAC.AddRegNT]
+HKLM,SOFTWARE\Microsoft\Windows NT\CurrentVersion\drivers.desc,aac_acm.dll,,%AACAudio%
+HKLM,SOFTWARE\Microsoft\Windows NT\CurrentVersion\drivers32,msacm.aac,,aac_acm.dll
+
+
+HKLM,%UnInstallPath%,DisplayName,,%UninstallDispName%
+HKLM,%UnInstallPath%,UninstallString,,"%11%\rundll32.exe setupapi,InstallHinfSection Remove_AAC 132 %17%\%InfFile%"
+
+[AAC.DelReg]
+HKLM,SYSTEM\CurrentControlSet\Control\MediaResources\acm\msacm.aac
+
+HKLM,SOFTWARE\Microsoft\Windows NT\CurrentVersion\drivers.desc,aac_acm.dll,,""
+HKLM,SOFTWARE\Microsoft\Windows NT\CurrentVersion\drivers32,msacm.aac,,""
+HKLM,%UnInstallPath%
+
+[DestinationDirs]
+DefaultDestDir = 11	; LDID_SYS
+AAC.Copy = 11
+AAC.Copy.Inf = 17
+
+[Strings]
+AACAudio="MPEG-2/4 AAC audio codec"
+InfFile="aac_acm.inf"
+UninstallDispName="MPEG-2/4 AAC audio codec"
+UnInstallPath="Software\Microsoft\Windows\CurrentVersion\Uninstall\AACCodec"
+MediaClassName="Media Devices"
+mfgname="No more money !"
+
--- /dev/null
+++ b/plugins/aac_acm/codec.cpp
@@ -1,0 +1,660 @@
+#include "codec.h"
+//#include <assert.h>
+
+// we must register these by emailing to mmreg@microsoft.com
+const int codec::m_iCompressedFormatTag = 0x1234;
+const int codec::m_iManufacturerID = MM_GADGETLABS;
+const int codec::m_iProductID = 7;
+
+const wchar_t g_sCodecName[]=L"MPEG-2/4 AAC audio codec";
+const wchar_t g_sLongCodecName[]=L"Very special audio codec";
+const wchar_t g_sFormatName[]=L"MPEG-2/4 AAC";
+
+codec::codec()
+{
+}
+
+codec::~codec()
+{
+}
+
+HRESULT codec::formattag_details(ACMFORMATTAGDETAILSW* lParam1, DWORD lParam2)
+{
+    bool bCompressedFormat;
+    switch(lParam2)
+    {
+    case ACM_FORMATTAGDETAILSF_INDEX:
+		if(lParam1->dwFormatTagIndex>=2)
+			return ACMERR_NOTPOSSIBLE;
+		bCompressedFormat=(lParam1->dwFormatTagIndex==1);
+		break;
+    case ACM_FORMATTAGDETAILSF_FORMATTAG:
+		if(lParam1->dwFormatTag==1)
+			bCompressedFormat=false;
+		else if(lParam1->dwFormatTag==m_iCompressedFormatTag)
+			bCompressedFormat=true;
+		else
+			return ACMERR_NOTPOSSIBLE;
+    case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
+		bCompressedFormat=true;
+		break;
+    default:
+		return ACMERR_NOTPOSSIBLE;
+    }
+    lParam1->cbStruct=sizeof(ACMFORMATTAGDETAILSW);    
+    lParam1->cbFormatSize=bCompressedFormat ? 20 : 16;    
+    lParam1->fdwSupport=ACMDRIVERDETAILS_SUPPORTF_CODEC;
+    if(bCompressedFormat)
+		lParam1->cStandardFormats=8; // 44 & 48 khz 16 bit, mono & stereo, 64 & 128 kbps
+    else
+		lParam1->cStandardFormats=8; // 44 & 48 khz 8 & 16 bit, mono & stereo
+    if(bCompressedFormat)
+    {
+		wcscpy(lParam1->szFormatTag, g_sFormatName);
+		lParam1->dwFormatTag=m_iCompressedFormatTag;
+    }
+    else
+    {
+		wcscpy(lParam1->szFormatTag, L"PCM");
+		lParam1->dwFormatTag=1;
+    }
+    return MMSYSERR_NOERROR;
+}
+
+void codec::fill_pcm_format(WAVEFORMATEX* pwfx, int rate, int bits, int channels)
+{
+    pwfx->wFormatTag=1;
+    pwfx->nSamplesPerSec=rate;
+    pwfx->wBitsPerSample=bits;
+    pwfx->nChannels=channels;
+    pwfx->nAvgBytesPerSec=rate * bits * channels / 8;
+    pwfx->nBlockAlign=channels * bits / 8;
+    pwfx->cbSize=0;
+}
+
+#define MAIN 0
+#define LOW  1
+#define SSR  2
+#define LTP  3
+
+static unsigned int aacSamplingRates[16] = {
+    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+		16000, 12000, 11025, 8000, 7350, 0, 0, 0
+};
+
+void codec::fill_compressed_format(WAVEFORMATEX* pwfx, int rate, int bits, int channels, int bitrate)
+{
+    pwfx->wFormatTag=m_iCompressedFormatTag;
+    pwfx->nSamplesPerSec=rate;
+    pwfx->wBitsPerSample=bits;
+    pwfx->nChannels=channels;
+    pwfx->nAvgBytesPerSec=bitrate / 8;
+    pwfx->nBlockAlign=1024;
+    pwfx->cbSize=2;
+	
+    unsigned char* ext=(unsigned char*)(&pwfx[1]);
+    int profile = MAIN;
+    int samplerate_index=-1;
+    for(int i=0; i<16; i++)
+		if(aacSamplingRates[i]==rate)
+		{
+			samplerate_index=i;
+			break;
+		}
+		if(samplerate_index<0)
+			return;
+		ext[0] = ((profile + 1) << 3) | ((samplerate_index & 0xe) >> 1);
+		ext[1] = ((samplerate_index & 0x1) << 7) | (channels << 3);
+		// 960 byte frames not used
+}
+
+HRESULT codec::format_details(ACMFORMATDETAILSW* lParam1, DWORD lParam2)
+{
+    lParam1->cbStruct=sizeof(ACMFORMATDETAILSW);
+    lParam1->szFormat[0]=0;
+    lParam1->fdwSupport=ACMDRIVERDETAILS_SUPPORTF_CODEC;
+	
+    if(lParam1->dwFormatTag==1)
+    {
+		if(lParam2==ACM_FORMATDETAILSF_INDEX)
+		{
+			switch(lParam1->dwFormatIndex)
+			{
+			case 0:
+				fill_pcm_format(lParam1->pwfx, 44100, 16, 1);
+				break;
+			case 1:
+				fill_pcm_format(lParam1->pwfx, 44100, 16, 2);
+				break;
+			case 2:
+				fill_pcm_format(lParam1->pwfx, 44100, 8, 1);
+				break;
+			case 3:
+				fill_pcm_format(lParam1->pwfx, 44100, 8, 2);
+				break;
+			case 4:
+				fill_pcm_format(lParam1->pwfx, 48000, 16, 1);
+				break;
+			case 5:
+				fill_pcm_format(lParam1->pwfx, 48000, 16, 2);
+				break;
+			case 6:
+				fill_pcm_format(lParam1->pwfx, 48000, 8, 1);
+				break;
+			case 7:
+				fill_pcm_format(lParam1->pwfx, 48000, 8, 2);
+				break;
+			default:
+				return ACMERR_NOTPOSSIBLE;
+			}
+		}   
+		else if(lParam2==ACM_FORMATDETAILSF_FORMAT)
+		{
+			if((lParam1->pwfx->nSamplesPerSec != 44100) && (lParam1->pwfx->nSamplesPerSec != 48000))
+				return ACMERR_NOTPOSSIBLE;
+		}
+		else
+			return ACMERR_NOTPOSSIBLE;
+    }
+    else if(lParam1->dwFormatTag==m_iCompressedFormatTag)
+    {
+		if(lParam2==ACM_FORMATDETAILSF_INDEX)
+		{
+			switch(lParam1->dwFormatIndex)
+			{
+			case 0:
+				fill_compressed_format(lParam1->pwfx, 44100, 16, 1, 128000);
+				break;
+			case 1:
+				fill_compressed_format(lParam1->pwfx, 44100, 16, 2, 128000);
+				break;
+			case 2:
+				fill_compressed_format(lParam1->pwfx, 44100, 16, 1, 64000);
+				break;
+			case 3:
+				fill_compressed_format(lParam1->pwfx, 44100, 16, 2, 64000);
+				break;
+			case 4:
+				fill_compressed_format(lParam1->pwfx, 48000, 16, 1, 128000);
+				break;
+			case 5:
+				fill_compressed_format(lParam1->pwfx, 48000, 16, 2, 128000);
+				break;
+			case 6:
+				fill_compressed_format(lParam1->pwfx, 48000, 16, 1, 64000);
+				break;
+			case 7:
+				fill_compressed_format(lParam1->pwfx, 48000, 16, 2, 64000);
+				break;
+			default:
+				return ACMERR_NOTPOSSIBLE;
+			}
+		}
+		else if(lParam2==ACM_FORMATDETAILSF_FORMAT)
+		{
+			if((lParam1->pwfx->nSamplesPerSec != 44100) && (lParam1->pwfx->nSamplesPerSec != 48000))
+				return ACMERR_NOTPOSSIBLE;
+		}
+		else
+			return ACMERR_NOTPOSSIBLE;
+    }
+    else
+		return ACMERR_NOTPOSSIBLE;
+    return MMSYSERR_NOERROR;
+}
+
+HRESULT codec::format_suggest(ACMDRVFORMATSUGGEST* pFormat)
+{
+    bool bEncode;
+    if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)
+    {
+		if((pFormat->pwfxDst->wFormatTag == 1) && (pFormat->pwfxSrc->wFormatTag == m_iCompressedFormatTag))
+			bEncode=false;
+		else
+			if((pFormat->pwfxDst->wFormatTag == m_iCompressedFormatTag) && (pFormat->pwfxSrc->wFormatTag == 1))
+				bEncode=true;
+			else
+				return ACMERR_NOTPOSSIBLE;
+    }
+    else
+    {
+		if(pFormat->pwfxSrc->wFormatTag == m_iCompressedFormatTag)
+		{
+			pFormat->pwfxDst->wFormatTag=1; 
+			bEncode=false;
+		}
+		else
+			if(pFormat->pwfxSrc->wFormatTag == 1)
+			{
+				pFormat->pwfxDst->wFormatTag=m_iCompressedFormatTag; 
+				bEncode=true;
+			}
+			else
+				return ACMERR_NOTPOSSIBLE;
+    }
+    if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS)
+    {
+		if(pFormat->pwfxDst->nChannels != pFormat->pwfxSrc->nChannels)
+			return ACMERR_NOTPOSSIBLE;
+    }
+    int iChannels = pFormat->pwfxSrc->nChannels;
+    if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)
+    {
+		if(pFormat->pwfxDst->nSamplesPerSec != pFormat->pwfxSrc->nSamplesPerSec)
+			return ACMERR_NOTPOSSIBLE;
+    }
+    int iSamplesPerSec = pFormat->pwfxSrc->nSamplesPerSec;
+	
+    if(pFormat->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)
+    {
+		if(pFormat->pwfxDst->wBitsPerSample != pFormat->pwfxSrc->wBitsPerSample)
+			return ACMERR_NOTPOSSIBLE;
+    }
+    int iBitsPerSample = pFormat->pwfxSrc->wBitsPerSample;
+	
+    if(bEncode)
+		fill_compressed_format(pFormat->pwfxDst, iSamplesPerSec, iBitsPerSample, iChannels, 128000);
+    else
+		fill_pcm_format(pFormat->pwfxDst, iSamplesPerSec, iBitsPerSample, iChannels);
+	
+    return MMSYSERR_NOERROR;
+}
+
+HRESULT codec::details(ACMDRIVERDETAILSW* pDetails)
+{
+    memset(pDetails, 0, sizeof(ACMDRIVERDETAILSW));
+    pDetails->cbStruct=sizeof(ACMDRIVERDETAILSW);
+    pDetails->fccType=ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
+    pDetails->fccComp=ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
+    pDetails->wMid=m_iManufacturerID;
+    pDetails->wPid=m_iProductID;
+    pDetails->vdwACM=0x3320000;
+    pDetails->vdwDriver=0x1000000;
+    pDetails->fdwSupport=ACMDRIVERDETAILS_SUPPORTF_CODEC;
+    pDetails->cFormatTags=2;
+    pDetails->cFilterTags=0;
+    wcscpy(pDetails->szShortName, g_sCodecName);
+    wcscpy(pDetails->szLongName, g_sLongCodecName);
+    return MMSYSERR_NOERROR;
+}
+
+HRESULT codec::about(DWORD h)
+{
+    if(h==(DWORD)-1)
+		return MMSYSERR_NOERROR;
+    MessageBoxW((HWND)h, g_sLongCodecName, L"About", MB_OK);
+    return MMSYSERR_NOERROR;
+}
+
+HRESULT codec::open(ACMDRVSTREAMINSTANCE* pStream)
+{
+    if(pStream->pwfxDst->nChannels != pStream->pwfxSrc->nChannels)
+		return ACMERR_NOTPOSSIBLE;
+    if(pStream->pwfxDst->nSamplesPerSec != pStream->pwfxSrc->nSamplesPerSec)
+		return ACMERR_NOTPOSSIBLE;
+    bool bDecode = (pStream->pwfxDst->wFormatTag == 1);
+    if(bDecode)
+    {
+		if(pStream->pwfxDst->wBitsPerSample!=16)
+			return ACMERR_NOTPOSSIBLE;
+		if(pStream->pwfxSrc->wFormatTag!=m_iCompressedFormatTag)
+			return ACMERR_NOTPOSSIBLE;
+    }
+    else
+    {
+		//	if(pStream->pwfxSrc->wBitsPerSample!=16)
+		//	    return ACMERR_NOTPOSSIBLE;
+		if(pStream->pwfxDst->wFormatTag!=m_iCompressedFormatTag)
+			return ACMERR_NOTPOSSIBLE;
+		if(pStream->pwfxSrc->wFormatTag!=1)
+			return ACMERR_NOTPOSSIBLE;
+    }
+	
+    if(pStream->fdwOpen & ACM_STREAMOPENF_QUERY)
+		return MMSYSERR_NOERROR;
+	
+    if(bDecode)
+		pStream->dwDriver=(DWORD)new decoder(pStream->pwfxSrc);
+    else
+		pStream->dwDriver=(DWORD)new encoder(pStream->pwfxSrc, pStream->pwfxDst);
+    return MMSYSERR_NOERROR;
+}
+
+HRESULT codec::prepare(ACMDRVSTREAMINSTANCE* pStream, ACMDRVSTREAMHEADER* pHeader)
+{
+    return MMSYSERR_NOTSUPPORTED;
+}
+
+HRESULT codec::reset(ACMDRVSTREAMINSTANCE* pStream)
+{
+    stream* pstr=(stream*)pStream->dwDriver;
+    return pstr->reset();
+}
+
+HRESULT codec::size(ACMDRVSTREAMINSTANCE* pStream, ACMDRVSTREAMSIZE* pSize)
+{
+    stream* pstr=(stream*)pStream->dwDriver;
+    return pstr->size(pSize);
+}
+
+HRESULT codec::unprepare(ACMDRVSTREAMINSTANCE* pStream, ACMDRVSTREAMHEADER* pHeader)
+{
+    return MMSYSERR_NOTSUPPORTED;
+}
+
+HRESULT codec::convert(ACMDRVSTREAMINSTANCE* pStream, ACMDRVSTREAMHEADER* pHeader)
+{
+    stream* pstr=(stream*)pStream->dwDriver;
+    return pstr->convert(pHeader);
+}
+
+HRESULT codec::close(ACMDRVSTREAMINSTANCE* pStream)
+{
+    stream* pstr=(stream*)pStream->dwDriver;
+    delete pstr;
+    return MMSYSERR_NOERROR;
+}
+
+#include "faac.h"
+
+codec::encoder::encoder(WAVEFORMATEX* pF, WAVEFORMATEX* pFDest) : m_sFormat(*pF)
+{
+    m_iOutputBytesPerSec=pFDest->nAvgBytesPerSec; 
+	
+    m_pHandle=faacEncOpen(pF->nSamplesPerSec, pF->nChannels, &m_iInputSamples, &m_iMaxOutputBytes);
+	
+    faacEncConfiguration conf;
+    conf.mpegVersion = MPEG4;
+    conf.aacObjectType = MAIN;
+    conf.allowMidside = 1;
+    conf.useLfe = 1;
+    conf.useTns = 1;
+    conf.bitRate = m_iOutputBytesPerSec/pFDest->nChannels; // bits/second per channel
+    conf.bandWidth = 18000; //Hz
+    conf.outputFormat = 1; // ADTS
+    faacEncSetConfiguration(m_pHandle, &conf);    
+}
+
+HRESULT codec::encoder::reset()
+{
+    // fixme (?)
+    return MMSYSERR_NOERROR;
+}
+
+HRESULT codec::encoder::size(ACMDRVSTREAMSIZE* pSize)
+{
+    double dwInputBitRate=m_sFormat.nSamplesPerSec * m_sFormat.wBitsPerSample * m_sFormat.nChannels;
+    double dwOutputBitRate=m_iOutputBytesPerSec;// kbytes/s    
+	
+    if(pSize->fdwSize == ACM_STREAMSIZEF_SOURCE)
+    {
+		if(pSize->cbSrcLength<2*m_iInputSamples)
+			pSize->cbSrcLength=2*m_iInputSamples;
+		pSize->cbDstLength = pSize->cbSrcLength * 2 * dwOutputBitRate/dwInputBitRate;
+		if(pSize->cbDstLength<m_iMaxOutputBytes)
+			pSize->cbDstLength=m_iMaxOutputBytes;
+		
+    }
+    else
+    {
+		if(pSize->cbDstLength<m_iMaxOutputBytes)
+			pSize->cbDstLength=m_iMaxOutputBytes;
+		pSize->cbSrcLength = pSize->cbDstLength * 2 * dwInputBitRate/dwOutputBitRate;;
+		if(pSize->cbSrcLength<2*m_iInputSamples)
+			pSize->cbSrcLength=2*m_iInputSamples;
+    }
+    
+    return MMSYSERR_NOERROR;
+}
+
+#include <stdio.h>
+
+HRESULT codec::encoder::convert(ACMDRVSTREAMHEADER* pHeader)
+{
+#if 0
+    short* pSrc, *pDst;
+    pSrc=(short*)(pHeader->pbSrc);
+    pDst=(short*)(pHeader->pbDst);
+    int iSrc=0, iDst=0;
+    int block_size=m_sFormat.nChannels * 64;
+    int samples_to_process=pHeader->cbSrcLength / (2 * block_size);
+	
+    for(int j=0; j<samples_to_process; j++)
+    {
+		if(m_sFormat.nChannels==1)
+		{
+			pDst[0]=pSrc[0];
+			for(int i=1; i<64; i++)
+				pDst[i]=(int)pSrc[i]-(int)pSrc[i-1];
+			pSrc+=block_size;
+			pDst+=block_size;
+		}
+		else
+		{
+			pDst[0]=pSrc[0];
+			pDst[1]=pSrc[1];
+			for(int i=1; i<64; i++)
+			{
+				pDst[2*i]=(int)pSrc[2*i]-(int)pSrc[2*i-2];
+				pDst[2*i+1]=(int)pSrc[2*i+1]-(int)pSrc[2*i-1];
+			}
+			pSrc+=block_size;
+			pDst+=block_size;
+		}
+    }
+    FILE* f=fopen("c:\\enc.log", "ab");
+    fwrite(pHeader->pbSrc, 2 * block_size * samples_to_process, 1, f);
+    fclose(f);
+    f=fopen("c:\\enc2.log", "ab");
+    fwrite(pHeader->pbDst, 2 * block_size * samples_to_process, 1, f);
+    fclose(f);
+    pHeader->cbDstLengthUsed=2 * block_size * samples_to_process;
+    pHeader->cbSrcLengthUsed=2 * block_size * samples_to_process;
+    return MMSYSERR_NOERROR;
+#else
+    short* buffer=0;
+    int length=pHeader->cbSrcLength;
+    if(m_sFormat.wBitsPerSample!=16)
+    {
+		buffer = new short[length];
+		for(int i=0; i<length; i++)
+		{
+			short s=(short)(((unsigned char*)pHeader->pbSrc)[i]);
+			s-=128;
+			s*=256;
+			buffer[i]=s;
+		}
+    }
+    short* pointer = buffer ? buffer : (short*)(pHeader->pbSrc);
+    pHeader->cbSrcLengthUsed=0;
+    pHeader->cbDstLengthUsed=0;
+    while(1)
+    {
+		if(length-pHeader->cbSrcLengthUsed<2*m_iInputSamples)
+			break;
+		if(pHeader->cbDstLength-pHeader->cbDstLengthUsed<m_iMaxOutputBytes)
+			break;
+		int result=faacEncEncode(m_pHandle, pointer+pHeader->cbSrcLengthUsed,
+			m_iInputSamples, 
+			(short*)(pHeader->pbDst+pHeader->cbDstLengthUsed),
+			pHeader->cbDstLength-pHeader->cbDstLengthUsed);
+		if(result<0)
+		{
+			reset();
+			break;
+		}
+        pHeader->cbDstLengthUsed+=result;
+        pHeader->cbSrcLengthUsed+=2*m_iInputSamples;
+    }    
+    if(buffer)
+    {
+		pHeader->cbSrcLengthUsed/=2;
+		delete[] buffer;
+    }
+    return MMSYSERR_NOERROR;
+#endif
+}
+
+codec::decoder::decoder(WAVEFORMATEX* pF) : m_sFormat(*pF), m_bInitialized(false), m_pCache(0)
+{
+    m_pHandle=faacDecOpen();
+}
+
+HRESULT codec::decoder::reset()
+{
+    faacDecClose(m_pHandle);
+    m_pHandle=faacDecOpen();
+    m_bInitialized=false;
+    delete[] m_pCache;
+    m_pCache=0;
+    return MMSYSERR_NOERROR;
+}
+
+HRESULT codec::decoder::size(ACMDRVSTREAMSIZE* pSize)
+{
+    double dwInputBitRate=m_sFormat.nAvgBytesPerSec;
+    double dwOutputBitRate=m_sFormat.nSamplesPerSec * m_sFormat.wBitsPerSample * m_sFormat.nChannels;
+	
+    if(pSize->fdwSize == ACM_STREAMSIZEF_SOURCE)
+    {
+		if(pSize->cbSrcLength<768*m_sFormat.nChannels)
+			pSize->cbSrcLength=768*m_sFormat.nChannels;
+		pSize->cbDstLength = pSize->cbSrcLength * 2 * dwOutputBitRate/dwInputBitRate;
+		if(pSize->cbDstLength<4096)
+			pSize->cbDstLength=4096;
+    }
+    else
+    {
+		if(pSize->cbDstLength<4096)
+			pSize->cbDstLength=4096;
+		pSize->cbSrcLength = pSize->cbDstLength * 2 * dwInputBitRate/dwOutputBitRate;;
+		if(pSize->cbSrcLength<768*m_sFormat.nChannels)
+			pSize->cbSrcLength=768*m_sFormat.nChannels;
+    }
+    
+    return MMSYSERR_NOERROR;
+}
+
+//static int iBytesProcessed=0;
+HRESULT codec::decoder::convert(ACMDRVSTREAMHEADER* pHeader)
+{
+#if 0
+    short *pSrc, *pDst;
+    pSrc=(short*)pHeader->pbSrc;
+    pDst=(short*)pHeader->pbDst;
+    int iSrc=0, iDst=0;
+    int block_size=m_sFormat.nChannels * 64;
+    int samples_to_process=pHeader->cbSrcLength / (2 * block_size);
+    for(int j=0; j<samples_to_process; j++)
+    {
+		if(m_sFormat.nChannels==1)
+		{
+			pDst[0]=pSrc[0];
+			for(int i=1; i<64; i++)
+				pDst[i]=(int)pSrc[i]+(int)pDst[i-1];
+			pSrc+=block_size;
+			pDst+=block_size;
+		}
+		else
+		{
+			pDst[0]=pSrc[0];
+			pDst[1]=pSrc[1];
+			for(int i=1; i<64; i++)
+			{
+				pDst[2*i]=(int)pSrc[2*i]+(int)pDst[2*i-2];
+				pDst[2*i+1]=(int)pSrc[2*i+1]+(int)pDst[2*i-1];
+			}
+			pSrc+=block_size;
+			pDst+=block_size;
+		}
+    }
+    FILE* f=fopen("c:\\dec.log", "ab");
+    fwrite(pHeader->pbDst, 2 * block_size * samples_to_process, 1, f);
+    fclose(f);
+    pHeader->cbDstLengthUsed=2 * block_size * samples_to_process;
+    pHeader->cbSrcLengthUsed=2 * block_size * samples_to_process;
+    return MMSYSERR_NOERROR;
+#else
+    // fixme: check fdwConvert contents
+	
+    const int iMinInputSize = 768*m_sFormat.nChannels;
+    pHeader->cbSrcLengthUsed=0;
+    pHeader->cbDstLengthUsed=0;
+    int decoded_bytes=0;
+    if(!m_bInitialized)
+    {
+		unsigned long samplerate;
+		unsigned long channels;
+		//assert(!m_pCache);
+		// we don't really need this call
+		// and it is done only because i am not sure if it's necessary for faac functionality
+		pHeader->cbSrcLengthUsed=faacDecInit(m_pHandle, pHeader->pbSrc, &samplerate, &channels);
+		m_bInitialized=true;
+    }
+    unsigned long bytesconsumed;
+    unsigned long samples;    
+    if(pHeader->cbDstLength<4096)
+		goto finish;
+	
+    if(m_pCache)
+    {
+		int iFillSize = iMinInputSize - m_iCacheSize;
+		if(iFillSize > pHeader->cbSrcLength)
+			iFillSize = pHeader->cbSrcLength;
+		memcpy(&m_pCache[m_iCacheSize], pHeader->pbSrc, iFillSize);
+		m_iCacheSize += iFillSize;
+		pHeader->cbSrcLengthUsed = iFillSize;
+		if(m_iCacheSize == iMinInputSize)
+		{
+			int result=faacDecDecode(m_pHandle, pHeader->pbSrc+pHeader->cbSrcLengthUsed, &bytesconsumed, 
+				(short*)(pHeader->pbDst+pHeader->cbDstLengthUsed), &samples); // no way to prevent output buffer overrun???
+			if(result==FAAD_FATAL_ERROR)
+				reset();
+			if(result==FAAD_OK)
+				pHeader->cbDstLengthUsed+=sizeof(short)*samples;
+			delete[] m_pCache;
+			m_pCache=0;
+			goto finish;
+		}
+    }
+	
+    int iSrcDataLeft=pHeader->cbSrcLength-pHeader->cbSrcLengthUsed;
+    
+    if(iSrcDataLeft == 0)
+		goto finish;
+	
+	
+    if(iSrcDataLeft < iMinInputSize)
+    {
+		m_pCache = new unsigned char[iMinInputSize];
+		memcpy(m_pCache, pHeader->pbSrc + pHeader->cbSrcLengthUsed, iSrcDataLeft);
+		pHeader->cbSrcLengthUsed = pHeader->cbSrcLength;
+		goto finish;
+    }
+    
+    while(iSrcDataLeft>=iMinInputSize)
+    {
+		if(pHeader->cbDstLength-pHeader->cbDstLengthUsed<4096)
+			break;
+		int result=faacDecDecode(m_pHandle, pHeader->pbSrc+pHeader->cbSrcLengthUsed, &bytesconsumed, 
+			(short*)(pHeader->pbDst+pHeader->cbDstLengthUsed), &samples); // no way to prevent output buffer overrun???
+		if(result==FAAD_FATAL_ERROR)
+		{
+			pHeader->cbSrcLengthUsed=pHeader->cbSrcLength;
+			reset();
+			break;
+		}
+		if(result==FAAD_OK)
+			pHeader->cbDstLengthUsed+=sizeof(short)*samples;
+        pHeader->cbSrcLengthUsed+=bytesconsumed;
+		iSrcDataLeft-=bytesconsumed;
+    }    
+finish:
+    FILE* f=fopen("c:\\aac_acm.bin", "ab");
+    fwrite(pHeader->pbSrc, pHeader->cbSrcLengthUsed, 1, f);
+    fclose(f);
+	//    iBytesProcessed+=pHeader->cbSrcLengthUsed;
+    return MMSYSERR_NOERROR;
+#endif
+}
+
--- /dev/null
+++ b/plugins/aac_acm/codec.h
@@ -1,0 +1,71 @@
+#ifndef _CODEC_H
+#define _CODEC_H
+
+#include "msacmdrv.h"
+#include "faac.h"
+#include "faad.h"
+class codec
+{
+    static const int m_iCompressedFormatTag;
+    static const int m_iManufacturerID;
+    static const int m_iProductID;
+	
+    static void fill_pcm_format(WAVEFORMATEX* pwfx, int rate, int bits, int channels);
+    static void fill_compressed_format(WAVEFORMATEX* pwfx, int rate, int bits, int channels, int bitrate);
+    int something;
+    class stream
+    {
+    public:
+		virtual ~stream() {}
+		virtual HRESULT reset() =0;
+		virtual HRESULT size(ACMDRVSTREAMSIZE*) =0;
+		virtual HRESULT convert(ACMDRVSTREAMHEADER*) =0;
+    };
+    class encoder: public stream
+    {
+		WAVEFORMATEX m_sFormat;
+		unsigned long m_iInputSamples;
+		unsigned long m_iMaxOutputBytes;
+		unsigned long m_iOutputBytesPerSec;
+		faacEncHandle m_pHandle;
+    public:
+		encoder(WAVEFORMATEX* pF, WAVEFORMATEX* pFDest);
+		~encoder() {}
+		virtual HRESULT reset();
+		virtual HRESULT size(ACMDRVSTREAMSIZE*);
+		virtual HRESULT convert(ACMDRVSTREAMHEADER*);
+    };
+    class decoder: public stream
+    {
+		WAVEFORMATEX m_sFormat;
+		faacDecHandle m_pHandle;
+		bool m_bInitialized;
+		unsigned char* m_pCache;
+		int m_iCacheSize;
+    public:
+		decoder(WAVEFORMATEX* pF);
+		~decoder() { delete[] m_pCache; }
+		virtual HRESULT reset();
+		virtual HRESULT size(ACMDRVSTREAMSIZE*);
+		virtual HRESULT convert(ACMDRVSTREAMHEADER*);
+    };
+	public:
+		codec();
+		~codec();
+		HRESULT formattag_details(ACMFORMATTAGDETAILSW* lParam1, DWORD lParam2);
+		HRESULT format_details(ACMFORMATDETAILSW* lParam1, DWORD lParam2);
+		HRESULT format_suggest(ACMDRVFORMATSUGGEST*);
+		HRESULT details(ACMDRIVERDETAILSW*);
+		HRESULT about(DWORD);
+		HRESULT open(ACMDRVSTREAMINSTANCE*);
+		HRESULT prepare(ACMDRVSTREAMINSTANCE*, ACMDRVSTREAMHEADER*);
+		HRESULT reset(ACMDRVSTREAMINSTANCE*);
+		HRESULT size(ACMDRVSTREAMINSTANCE*, ACMDRVSTREAMSIZE*);
+		HRESULT unprepare(ACMDRVSTREAMINSTANCE*, ACMDRVSTREAMHEADER*);
+		HRESULT convert(ACMDRVSTREAMINSTANCE*, ACMDRVSTREAMHEADER*);
+		HRESULT close(ACMDRVSTREAMINSTANCE*);
+};
+
+#endif
+
+
--- /dev/null
+++ b/plugins/aac_acm/msacmdrv.h
@@ -1,0 +1,178 @@
+#ifndef _MSACMDRV_H
+#define _MSACMDRV_H
+
+#include <windows.h>
+#include <mmsystem.h>
+#include <mmreg.h>
+#include <vfw.h>
+#include <msacm.h>
+
+#define ACMDM_DRIVER_DETAILS            (ACMDM_BASE + 10)
+#define ACMDM_DRIVER_ABOUT	        (ACMDM_BASE + 11)
+#define ACMDM_FORMATTAG_DETAILS         (ACMDM_BASE + 25)
+#define ACMDM_FORMAT_DETAILS            (ACMDM_BASE + 26)
+#define ACMDM_FORMAT_SUGGEST            (ACMDM_BASE + 27)
+
+#define ACMDM_STREAM_OPEN               (ACMDM_BASE + 76)
+#define ACMDM_STREAM_CLOSE              (ACMDM_BASE + 77)
+#define ACMDM_STREAM_SIZE               (ACMDM_BASE + 78)
+#define ACMDM_STREAM_CONVERT            (ACMDM_BASE + 79)
+#define ACMDM_STREAM_RESET              (ACMDM_BASE + 80)
+#define ACMDM_STREAM_PREPARE            (ACMDM_BASE + 81)
+#define ACMDM_STREAM_UNPREPARE          (ACMDM_BASE + 82)
+#define ACMDM_STREAM_UPDATE             (ACMDM_BASE + 83)
+
+typedef struct _ACMDRVOPENDESCA
+{
+  DWORD  cbStruct;
+  FOURCC fccType;
+  FOURCC fccComp;
+  DWORD  dwVersion;
+  DWORD  dwFlags;
+  DWORD  dwError;
+  LPCSTR pszSectionName;
+  LPCSTR pszAliasName;
+  DWORD  dnDevNode;
+} ACMDRVOPENDESCA, *PACMDRVOPENDESCA;
+
+typedef struct _ACMDRVOPENDESCW
+{
+  DWORD   cbStruct;
+  FOURCC  fccType;
+  FOURCC  fccComp;
+  DWORD   dwVersion;
+  DWORD   dwFlags;
+  DWORD   dwError;
+  LPCWSTR pszSectionName;
+  LPCWSTR pszAliasName;
+  DWORD   dnDevNode;
+} ACMDRVOPENDESCW, *PACMDRVOPENDESCW;
+
+typedef struct _ACMDRVOPENDESC16
+{
+  DWORD  cbStruct;
+  FOURCC fccType;
+  FOURCC fccComp;
+  DWORD  dwVersion;
+  DWORD  dwFlags;
+  DWORD  dwError;
+  LPCSTR pszSectionName;
+  LPCSTR pszAliasName;
+  DWORD  dnDevNode;
+} ACMDRVOPENDESC16, *NPACMDRVOPENDESC16, *LPACMDRVOPENDESC16;
+/*
+typedef struct _ACMDRVSTREAMINSTANCE16
+{
+  DWORD            cbStruct;
+  LPWAVEFORMATEX   pwfxSrc;
+  LPWAVEFORMATEX   pwfxDst;
+  LPWAVEFILTER     pwfltr;
+  DWORD            dwCallback;
+  DWORD            dwInstance;
+  DWORD            fdwOpen;
+  DWORD            fdwDriver;
+  DWORD            dwDriver;
+  HACMSTREAM16     has;
+} ACMDRVSTREAMINSTANCE16, *NPACMDRVSTREAMINSTANCE16, *LPACMDRVSTREAMINSTANCE16;
+*/
+typedef struct _ACMDRVSTREAMINSTANCE
+{
+  DWORD           cbStruct;
+  PWAVEFORMATEX   pwfxSrc;
+  PWAVEFORMATEX   pwfxDst;
+  PWAVEFILTER     pwfltr;
+  DWORD           dwCallback;
+  DWORD           dwInstance;
+  DWORD           fdwOpen;
+  DWORD           fdwDriver;
+  DWORD           dwDriver;
+  HACMSTREAM    has;
+} ACMDRVSTREAMINSTANCE, *PACMDRVSTREAMINSTANCE;
+
+
+typedef struct _ACMDRVSTREAMHEADER16 *LPACMDRVSTREAMHEADER16;
+typedef struct _ACMDRVSTREAMHEADER16 {
+  DWORD  cbStruct;
+  DWORD  fdwStatus;
+  DWORD  dwUser;
+  LPBYTE pbSrc;
+  DWORD  cbSrcLength;
+  DWORD  cbSrcLengthUsed;
+  DWORD  dwSrcUser;
+  LPBYTE pbDst;
+  DWORD  cbDstLength;
+  DWORD  cbDstLengthUsed;
+  DWORD  dwDstUser;
+
+  DWORD fdwConvert;
+  LPACMDRVSTREAMHEADER16 *padshNext;
+  DWORD fdwDriver;
+  DWORD dwDriver;
+
+  /* Internal fields for ACM */
+  DWORD  fdwPrepared;
+  DWORD  dwPrepared;
+  LPBYTE pbPreparedSrc;
+  DWORD  cbPreparedSrcLength;
+  LPBYTE pbPreparedDst;
+  DWORD  cbPreparedDstLength;
+} ACMDRVSTREAMHEADER16, *NPACMDRVSTREAMHEADER16;
+
+typedef struct _ACMDRVSTREAMHEADER *PACMDRVSTREAMHEADER;
+typedef struct _ACMDRVSTREAMHEADER {
+  DWORD  cbStruct;
+  DWORD  fdwStatus;
+  DWORD  dwUser;
+  LPBYTE pbSrc;
+  DWORD  cbSrcLength;
+  DWORD  cbSrcLengthUsed;
+  DWORD  dwSrcUser;
+  LPBYTE pbDst;
+  DWORD  cbDstLength;
+  DWORD  cbDstLengthUsed;
+  DWORD  dwDstUser;
+
+  DWORD fdwConvert;
+  PACMDRVSTREAMHEADER *padshNext;
+  DWORD fdwDriver;
+  DWORD dwDriver;
+
+  /* Internal fields for ACM */
+  DWORD  fdwPrepared;
+  DWORD  dwPrepared;
+  LPBYTE pbPreparedSrc;
+  DWORD  cbPreparedSrcLength;
+  LPBYTE pbPreparedDst;
+  DWORD  cbPreparedDstLength;
+} ACMDRVSTREAMHEADER;
+
+typedef struct _ACMDRVSTREAMSIZE
+{
+  DWORD cbStruct;
+  DWORD fdwSize;
+  DWORD cbSrcLength;
+  DWORD cbDstLength;
+} ACMDRVSTREAMSIZE16, *NPACMDRVSTREAMSIZE16, *LPACMDRVSTREAMSIZE16,
+  ACMDRVSTREAMSIZE, *PACMDRVSTREAMSIZE;
+
+typedef struct _ACMDRVFORMATSUGGEST16
+{
+  DWORD            cbStruct;
+  DWORD            fdwSuggest;
+  LPWAVEFORMATEX   pwfxSrc;
+  DWORD            cbwfxSrc;
+  LPWAVEFORMATEX   pwfxDst;
+  DWORD            cbwfxDst;
+} ACMDRVFORMATSUGGEST16, *NPACMDRVFORMATSUGGEST, *LPACMDRVFORMATSUGGEST;
+
+typedef struct _ACMDRVFORMATSUGGEST
+{
+  DWORD           cbStruct;
+  DWORD           fdwSuggest;
+  PWAVEFORMATEX   pwfxSrc;
+  DWORD           cbwfxSrc;
+  PWAVEFORMATEX   pwfxDst;
+  DWORD           cbwfxDst;
+} ACMDRVFORMATSUGGEST, *PACMDRVFORMATSUGGEST;
+
+#endif