📄 mpegl3.c
字号:
/* * MPEG Layer 3 handling * * Copyright (C) 2002 Eric Pouech * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <assert.h>#include <stdarg.h>#include <string.h>#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "winnls.h"#include "mmsystem.h"#include "mmreg.h"#include "msacm.h"#include "../msacmdrv.h"#include "mpg123.h"#include "mpglib.h"#include "wine/debug.h"WINE_DEFAULT_DEBUG_CHANNEL(mpeg3);/*********************************************************************** * MPEG3_drvOpen */static DWORD MPEG3_drvOpen(LPCSTR str){ return 1;}/*********************************************************************** * MPEG3_drvClose */static DWORD MPEG3_drvClose(DWORD dwDevID){ return 1;}typedef struct tagAcmMpeg3Data{ void (*convert)(PACMDRVSTREAMINSTANCE adsi, const unsigned char*, LPDWORD, unsigned char*, LPDWORD); struct mpstr mp;} AcmMpeg3Data;/* table to list all supported formats... those are the basic ones. this * also helps given a unique index to each of the supported formats */typedef struct{ int nChannels; int nBits; int rate;} Format;static Format PCM_Formats[] ={ {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000}, {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},};static Format MPEG3_Formats[] ={ {1, 0, 8000}, {2, 0, 8000}, {1, 0, 11025}, {2, 0, 11025}, {1, 0, 22050}, {2, 0, 22050}, {1, 0, 44100}, {2, 0, 44100},};#define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))#define NUM_MPEG3_FORMATS (sizeof(MPEG3_Formats) / sizeof(MPEG3_Formats[0]))/*********************************************************************** * MPEG3_GetFormatIndex */static DWORD MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx){ int i, hi; Format* fmts; switch (wfx->wFormatTag) { case WAVE_FORMAT_PCM: hi = NUM_PCM_FORMATS; fmts = PCM_Formats; break; case WAVE_FORMAT_MPEGLAYER3: hi = NUM_MPEG3_FORMATS; fmts = MPEG3_Formats; break; default: return 0xFFFFFFFF; } for (i = 0; i < hi; i++) { if (wfx->nChannels == fmts[i].nChannels && wfx->nSamplesPerSec == fmts[i].rate && wfx->wBitsPerSample == fmts[i].nBits) return i; } return 0xFFFFFFFF;}/*********************************************************************** * R16 * * Read a 16 bit sample (correctly handles endianess) */static inline short R16(const unsigned char* src){ return (short)((unsigned short)src[0] | ((unsigned short)src[1] << 8));}/*********************************************************************** * W16 * * Write a 16 bit sample (correctly handles endianess) */static inline void W16(unsigned char* dst, short s){ dst[0] = LOBYTE(s); dst[1] = HIBYTE(s);}static void mp3_horse(PACMDRVSTREAMINSTANCE adsi, const unsigned char* src, LPDWORD nsrc, unsigned char* dst, LPDWORD ndst){ AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver; int size, ret; DWORD dpos = 0; ret = decodeMP3(&amd->mp, (unsigned char*)src, *nsrc, dst, *ndst, &size); if (ret != MP3_OK) { *ndst = *nsrc = 0; return; } do { dpos += size; if (*ndst - dpos < 4608) break; ret = decodeMP3(&amd->mp, NULL, 0, dst + dpos, *ndst - dpos, &size); } while (ret == MP3_OK); *ndst = dpos;}/*********************************************************************** * MPEG3_DriverDetails * */static LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add){ add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC; add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED; add->wMid = 0xFF; add->wPid = 0x00; add->vdwACM = 0x01000000; add->vdwDriver = 0x01000000; add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; add->cFormatTags = 2; /* PCM, MPEG3 */ add->cFilterTags = 0; add->hicon = NULL; MultiByteToWideChar( CP_ACP, 0, "WINE-MPEG3", -1, add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1, add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team (based on mpglib by Michael Hipp)...", -1, add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1, add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) ); add->szFeatures[0] = 0; return MMSYSERR_NOERROR;}/*********************************************************************** * MPEG3_FormatTagDetails * */static LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery){ static WCHAR szPcm[]={'P','C','M',0}; static WCHAR szMpeg3[]={'M','P','e','g','3',0}; switch (dwQuery) { case ACM_FORMATTAGDETAILSF_INDEX: if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE; break; case ACM_FORMATTAGDETAILSF_LARGESTSIZE: if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN) { aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_MPEGLAYER3 is bigger than PCM */ break; } /* fall thru */ case ACM_FORMATTAGDETAILSF_FORMATTAG: switch (aftd->dwFormatTag) { case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break; case WAVE_FORMAT_MPEGLAYER3: aftd->dwFormatTagIndex = 1; break; default: return ACMERR_NOTPOSSIBLE; } break; default: WARN("Unsupported query %08lx\n", dwQuery); return MMSYSERR_NOTSUPPORTED; } aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC; switch (aftd->dwFormatTagIndex) { case 0: aftd->dwFormatTag = WAVE_FORMAT_PCM; aftd->cbFormatSize = sizeof(PCMWAVEFORMAT); aftd->cStandardFormats = NUM_PCM_FORMATS; lstrcpyW(aftd->szFormatTag, szPcm); break; case 1: aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3; aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT); aftd->cStandardFormats = NUM_MPEG3_FORMATS; lstrcpyW(aftd->szFormatTag, szMpeg3); break; } return MMSYSERR_NOERROR;}static void fill_in_wfx(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate){ MPEGLAYER3WAVEFORMAT* mp3wfx = (MPEGLAYER3WAVEFORMAT*)wfx; wfx->nAvgBytesPerSec = bit_rate / 8; if (cbwfx >= sizeof(WAVEFORMATEX)) wfx->cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX); if (cbwfx >= sizeof(MPEGLAYER3WAVEFORMAT)) { mp3wfx->wID = MPEGLAYER3_ID_MPEG; mp3wfx->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF; mp3wfx->nBlockSize = (bit_rate * 144) / wfx->nSamplesPerSec; mp3wfx->nFramesPerBlock = 1; mp3wfx->nCodecDelay = 0x0571; }}/*********************************************************************** * MPEG3_FormatDetails * */static LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery){ switch (dwQuery) { case ACM_FORMATDETAILSF_FORMAT: if (MPEG3_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE; break; case ACM_FORMATDETAILSF_INDEX: afd->pwfx->wFormatTag = afd->dwFormatTag; switch (afd->dwFormatTag) { case WAVE_FORMAT_PCM: if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE; afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate; afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits; /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible * afd->pwfx->cbSize = 0; */ afd->pwfx->nBlockAlign = (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8; afd->pwfx->nAvgBytesPerSec = afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign; break; case WAVE_FORMAT_MPEGLAYER3: if (afd->dwFormatIndex >= NUM_MPEG3_FORMATS) return ACMERR_NOTPOSSIBLE; afd->pwfx->nChannels = MPEG3_Formats[afd->dwFormatIndex].nChannels; afd->pwfx->nSamplesPerSec = MPEG3_Formats[afd->dwFormatIndex].rate; afd->pwfx->wBitsPerSample = MPEG3_Formats[afd->dwFormatIndex].nBits; afd->pwfx->nBlockAlign = 1; fill_in_wfx(afd->cbwfx, afd->pwfx, 192000); break; default: WARN("Unsupported tag %08lx\n", afd->dwFormatTag); return MMSYSERR_INVALPARAM; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -