Release 2.9.
[wine.git] / dlls / winemp3.acm / mpegl3.c
blobcc6008da59e4c4fdcc6a34b1928de899b6d9a432
1 /*
2 * MPEG Layer 3 handling
4 * Copyright (C) 2002 Eric Pouech
5 * Copyright (C) 2009 CodeWeavers, Aric Stewart
6 * Copyright (C) 2010 Kristofer Henriksson
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <assert.h>
28 #include <stdarg.h>
29 #include <string.h>
31 #ifdef HAVE_MPG123_H
32 # include <mpg123.h>
33 #else
34 # ifdef HAVE_COREAUDIO_COREAUDIO_H
35 # include <CoreFoundation/CoreFoundation.h>
36 # include <CoreAudio/CoreAudio.h>
37 # endif
38 # ifdef HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H
39 # include <AudioToolbox/AudioConverter.h>
40 # endif
41 #endif
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wingdi.h"
46 #include "winuser.h"
47 #include "winnls.h"
48 #include "mmsystem.h"
49 #include "mmreg.h"
50 #include "msacm.h"
51 #include "msacmdrv.h"
52 #include "wine/debug.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(mpeg3);
56 /* table to list all supported formats... those are the basic ones. this
57 * also helps given a unique index to each of the supported formats
59 typedef struct
61 int nChannels;
62 int nBits;
63 int rate;
64 } Format;
66 static const Format PCM_Formats[] =
68 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
69 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
70 {1, 8, 12000}, {2, 8, 12000}, {1, 16, 12000}, {2, 16, 12000},
71 {1, 8, 16000}, {2, 8, 16000}, {1, 16, 16000}, {2, 16, 16000},
72 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
73 {1, 8, 24000}, {2, 8, 24000}, {1, 16, 24000}, {2, 16, 24000},
74 {1, 8, 32000}, {2, 8, 32000}, {1, 16, 32000}, {2, 16, 32000},
75 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
76 {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}
79 static const Format MPEG3_Formats[] =
81 {1, 0, 8000}, {2, 0, 8000},
82 {1, 0, 11025}, {2, 0, 11025},
83 {1, 0, 12000}, {2, 0, 12000},
84 {1, 0, 16000}, {2, 0, 16000},
85 {1, 0, 22050}, {2, 0, 22050},
86 {1, 0, 24000}, {2, 0, 24000},
87 {1, 0, 32000}, {2, 0, 32000},
88 {1, 0, 44100}, {2, 0, 44100},
89 {1, 0, 48000}, {2, 0, 48000}
92 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
93 #define NUM_MPEG3_FORMATS (sizeof(MPEG3_Formats) / sizeof(MPEG3_Formats[0]))
95 /***********************************************************************
96 * MPEG3_GetFormatIndex
98 static DWORD MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx)
100 int i, hi;
101 const Format *fmts;
103 switch (wfx->wFormatTag)
105 case WAVE_FORMAT_PCM:
106 hi = NUM_PCM_FORMATS;
107 fmts = PCM_Formats;
108 break;
109 case WAVE_FORMAT_MPEG:
110 case WAVE_FORMAT_MPEGLAYER3:
111 hi = NUM_MPEG3_FORMATS;
112 fmts = MPEG3_Formats;
113 break;
114 default:
115 return 0xFFFFFFFF;
118 for (i = 0; i < hi; i++)
120 if (wfx->nChannels == fmts[i].nChannels &&
121 wfx->nSamplesPerSec == fmts[i].rate &&
122 (wfx->wBitsPerSample == fmts[i].nBits || !fmts[i].nBits))
123 return i;
126 return 0xFFFFFFFF;
129 #ifdef HAVE_MPG123_H
131 typedef struct tagAcmMpeg3Data
133 void (*convert)(PACMDRVSTREAMINSTANCE adsi,
134 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
135 mpg123_handle *mh;
136 } AcmMpeg3Data;
138 /***********************************************************************
139 * MPEG3_drvOpen
141 static LRESULT MPEG3_drvOpen(LPCSTR str)
143 mpg123_init();
144 return 1;
147 /***********************************************************************
148 * MPEG3_drvClose
150 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
152 mpg123_exit();
153 return 1;
157 static void mp3_horse(PACMDRVSTREAMINSTANCE adsi,
158 const unsigned char* src, LPDWORD nsrc,
159 unsigned char* dst, LPDWORD ndst)
161 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
162 int ret;
163 size_t size;
164 DWORD dpos = 0;
167 if (*nsrc > 0)
169 ret = mpg123_feed(amd->mh, src, *nsrc);
170 if (ret != MPG123_OK)
172 ERR("Error feeding data\n");
173 *ndst = *nsrc = 0;
174 return;
178 do {
179 size = 0;
180 ret = mpg123_read(amd->mh, dst + dpos, *ndst - dpos, &size);
181 if (ret == MPG123_ERR)
183 FIXME("Error occurred during decoding!\n");
184 *ndst = *nsrc = 0;
185 return;
188 if (ret == MPG123_NEW_FORMAT)
190 long rate;
191 int channels, enc;
192 mpg123_getformat(amd->mh, &rate, &channels, &enc);
193 TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
195 dpos += size;
196 if (dpos >= *ndst) break;
197 } while (ret != MPG123_ERR && ret != MPG123_NEED_MORE);
198 *ndst = dpos;
201 /***********************************************************************
202 * MPEG3_Reset
205 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
207 mpg123_feedseek(aad->mh, 0, SEEK_SET, NULL);
208 mpg123_close(aad->mh);
209 mpg123_open_feed(aad->mh);
212 /***********************************************************************
213 * MPEG3_StreamOpen
216 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
218 AcmMpeg3Data* aad;
219 int err;
221 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
223 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
224 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
225 return ACMERR_NOTPOSSIBLE;
227 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
228 if (aad == 0) return MMSYSERR_NOMEM;
230 adsi->dwDriver = (DWORD_PTR)aad;
232 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
233 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
235 goto theEnd;
237 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
238 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
239 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
241 /* resampling or mono <=> stereo not available
242 * MPEG3 algo only define 16 bit per sample output
244 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
245 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
246 adsi->pwfxDst->wBitsPerSample != 16)
247 goto theEnd;
248 aad->convert = mp3_horse;
249 aad->mh = mpg123_new(NULL,&err);
250 mpg123_open_feed(aad->mh);
252 #if MPG123_API_VERSION >= 31 /* needed for MPG123_IGNORE_FRAMEINFO enum value */
253 /* mpg123 may find a XING header in the mp3 and use that information
254 * to ask for seeks in order to read specific frames in the file.
255 * We cannot allow that since the caller application is feeding us.
256 * This fixes problems for mp3 files encoded with LAME (bug 42361)
258 mpg123_param(aad->mh, MPG123_ADD_FLAGS, MPG123_IGNORE_INFOFRAME, 0);
259 #endif
261 /* no encoding yet
262 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
263 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
265 else goto theEnd;
266 MPEG3_Reset(adsi, aad);
268 return MMSYSERR_NOERROR;
270 theEnd:
271 HeapFree(GetProcessHeap(), 0, aad);
272 adsi->dwDriver = 0L;
273 return MMSYSERR_NOTSUPPORTED;
276 /***********************************************************************
277 * MPEG3_StreamClose
280 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
282 mpg123_close(((AcmMpeg3Data*)adsi->dwDriver)->mh);
283 mpg123_delete(((AcmMpeg3Data*)adsi->dwDriver)->mh);
284 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
285 return MMSYSERR_NOERROR;
288 #elif defined(HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H)
290 static const unsigned short Mp3BitRates[2][16] =
292 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
293 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
296 static const unsigned short Mp3SampleRates[2][4] =
298 {44100, 48000, 32000, 0},
299 {22050, 24000, 16000, 0}
302 typedef struct tagAcmMpeg3Data
304 LRESULT (*convert)(PACMDRVSTREAMINSTANCE adsi, unsigned char*,
305 LPDWORD, unsigned char*, LPDWORD);
306 AudioConverterRef acr;
307 AudioStreamBasicDescription in,out;
309 AudioBufferList outBuffer;
310 AudioBuffer inBuffer;
312 SInt32 tagBytesLeft;
314 UInt32 NumberPackets;
315 AudioStreamPacketDescription *PacketDescriptions;
316 } AcmMpeg3Data;
318 /***********************************************************************
319 * MPEG3_drvOpen
321 static LRESULT MPEG3_drvOpen(LPCSTR str)
323 return 1;
326 /***********************************************************************
327 * MPEG3_drvClose
329 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
331 return 1;
335 When it asks for data, give it all we have. If we have no data, we assume
336 we will in the future, so give it no packets and return an error, which
337 signals that we will have more later.
339 static OSStatus Mp3AudioConverterComplexInputDataProc(
340 AudioConverterRef inAudioConverter,
341 UInt32 *ioNumberDataPackets,
342 AudioBufferList *ioData,
343 AudioStreamPacketDescription **outDataPacketDescription,
344 void *inUserData
347 AcmMpeg3Data *amd = (AcmMpeg3Data*)inUserData;
349 if (amd->inBuffer.mDataByteSize > 0)
351 *ioNumberDataPackets = amd->NumberPackets;
352 ioData->mNumberBuffers = 1;
353 ioData->mBuffers[0] = amd->inBuffer;
354 amd->inBuffer.mDataByteSize = 0;
355 if (outDataPacketDescription)
356 *outDataPacketDescription = amd->PacketDescriptions;
357 return noErr;
359 else
361 *ioNumberDataPackets = 0;
362 return -74;
367 Get the length of the current frame. We need to be at the start of a
368 frame now. The buffer must have at least the four bytes for the header.
370 static SInt32 Mp3GetPacketLength(const unsigned char* src)
372 unsigned char mpegv;
373 unsigned short brate, srate;
374 unsigned int size;
377 Check that our position looks like an MP3 header and see which type
378 of MP3 file we have.
380 if (src[0] == 0xff && src[1] >> 1 == 0x7d) mpegv = 0; /* MPEG-1 File */
381 else if (src[0] == 0xff && src[1] >> 1 == 0x79) mpegv = 1; /* MPEG-2 File */
382 else return -1;
384 /* Fill in bit rate and sample rate. */
385 brate = Mp3BitRates[mpegv][(src[2] & 0xf0) >> 4];
386 srate = Mp3SampleRates[mpegv][(src[2] & 0xc) >> 2];
388 /* Certain values for bit rate and sample rate are invalid. */
389 if (brate == 0 || srate == 0) return -1;
391 /* Compute frame size, round down */
392 size = 72 * (2 - mpegv) * brate * 1000 / srate;
394 /* If there is padding, add one byte */
395 if (src[2] & 0x2) return size + 1;
396 else return size;
400 Apple's AudioFileStream does weird things so we deal with parsing the
401 file ourselves. It was also designed for a different use case, so this
402 is not unexpected. We expect to have MP3 data as input (i.e. we can only
403 deal with MPEG-1 or MPEG-2 Layer III), which simplifies parsing a bit. We
404 understand the ID3v2 header and skip over it. Whenever we have data we
405 want to skip at the beginning of the input, we do this by setting *ndst=0
406 and *nsrc to the length of the unwanted data and return no error.
408 static LRESULT mp3_leopard_horse(PACMDRVSTREAMINSTANCE adsi,
409 unsigned char* src, LPDWORD nsrc,
410 unsigned char* dst, LPDWORD ndst)
412 OSStatus err;
413 UInt32 size, aspdi, synci, syncSkip;
414 short framelen[4];
415 const unsigned char* psrc;
416 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
418 TRACE("ndst %u %p <- %u %p\n", *ndst, dst, *nsrc, src);
420 TRACE("First 16 bytes to input: %s\n", wine_dbgstr_an((const char *)src, 16));
422 /* Parse ID3 tag */
423 if (!memcmp(src, "ID3", 3) && amd->tagBytesLeft == -1)
425 amd->tagBytesLeft = (src[6] << 21) + (src[7] << 14) + (src[8] << 7) + src[9];
426 if (src[5] & 0x10) amd->tagBytesLeft += 20; /* There is a footer */
427 else amd->tagBytesLeft += 10;
430 /* Consume the tag */
431 if (amd->tagBytesLeft >= (SInt32)*nsrc)
433 *ndst = 0;
434 amd->tagBytesLeft -= *nsrc;
436 TRACE("All %d bytes of source data is ID3 tag\n", *nsrc);
437 return MMSYSERR_NOERROR;
439 else if (amd->tagBytesLeft > 0)
441 src += amd->tagBytesLeft;
442 *nsrc -= amd->tagBytesLeft;
443 TRACE("Skipping %ld for ID3 tag\n", amd->tagBytesLeft);
447 Sync to initial MP3 frame. The largest possible MP3 frame is 1440.
448 Thus, in the first 1440 bytes we must find the beginning of 3 valid
449 frames in a row unless we reach the end of the file first.
451 syncSkip = 0;
452 for (psrc = src; psrc <= src + *nsrc - 4 && psrc < src + 1440; psrc++)
454 framelen[0] = 0;
455 for (synci = 1;
456 synci < 4 && psrc + framelen[synci-1] < src + *nsrc - 4;
457 synci++)
459 framelen[synci] = Mp3GetPacketLength(psrc + framelen[synci-1]);
460 if (framelen[synci] == -1)
462 synci = 0;
463 break;
465 framelen[synci] += framelen[synci-1];
467 if (synci > 0) /* We synced successfully */
469 if (psrc - src > 0)
471 syncSkip = psrc - src;
472 src += syncSkip;
473 *nsrc -= syncSkip;
474 TRACE("Skipping %ld for frame sync\n", syncSkip);
476 break;
480 if (Mp3GetPacketLength(src) == -1)
482 *ndst = *nsrc = 0;
483 ERR("Frame sync failed. Cannot play file.\n");
484 return MMSYSERR_ERROR;
488 Fill in frame descriptions for all frames. We use an extra pointer
489 to keep track of our position in the input.
492 amd->NumberPackets = 25; /* This is the initial array capacity */
493 amd->PacketDescriptions = HeapAlloc(GetProcessHeap(), 0, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
494 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
496 for (aspdi = 0, psrc = src;
497 psrc <= src + *nsrc - 4;
498 psrc += amd->PacketDescriptions[aspdi].mDataByteSize, aspdi++)
500 /* Return an error if we can't read the frame header */
501 if (Mp3GetPacketLength(psrc) == -1)
503 *ndst = *nsrc = 0;
504 ERR("Invalid header at %p.\n", psrc);
505 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
506 return MMSYSERR_ERROR;
509 /* If we run out of space, double size and reallocate */
510 if (aspdi >= amd->NumberPackets)
512 amd->NumberPackets *= 2;
513 amd->PacketDescriptions = HeapReAlloc(GetProcessHeap(), 0, amd->PacketDescriptions, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
514 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
517 /* Fill in packet data */
518 amd->PacketDescriptions[aspdi].mStartOffset = psrc - src;
519 amd->PacketDescriptions[aspdi].mVariableFramesInPacket = 0;
520 amd->PacketDescriptions[aspdi].mDataByteSize = Mp3GetPacketLength(psrc);
522 /* If this brings us past the end, the last one doesn't count */
523 if (psrc + amd->PacketDescriptions[aspdi].mDataByteSize > src + *nsrc) break;
526 /* Fill in correct number of frames */
527 amd->NumberPackets = aspdi;
529 /* Adjust nsrc to only include full frames */
530 *nsrc = psrc - src;
532 amd->inBuffer.mDataByteSize = *nsrc;
533 amd->inBuffer.mData = src;
534 amd->inBuffer.mNumberChannels = amd->in.mChannelsPerFrame;
536 amd->outBuffer.mNumberBuffers = 1;
537 amd->outBuffer.mBuffers[0].mDataByteSize = *ndst;
538 amd->outBuffer.mBuffers[0].mData = dst;
539 amd->outBuffer.mBuffers[0].mNumberChannels = amd->out.mChannelsPerFrame;
541 /* Convert the data */
542 size = amd->outBuffer.mBuffers[0].mDataByteSize / amd->out.mBytesPerPacket;
543 err = AudioConverterFillComplexBuffer(amd->acr, Mp3AudioConverterComplexInputDataProc, amd, &size, &amd->outBuffer, 0);
545 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
547 /* Add skipped bytes back into *nsrc */
548 if (amd->tagBytesLeft > 0)
550 *nsrc += amd->tagBytesLeft;
551 amd->tagBytesLeft = 0;
553 *nsrc += syncSkip;
555 if (err != noErr && err != -74)
557 *ndst = *nsrc = 0;
558 ERR("Feed Error: %ld\n", err);
559 return MMSYSERR_ERROR;
562 *ndst = amd->outBuffer.mBuffers[0].mDataByteSize;
564 TRACE("convert %d -> %d\n", *nsrc, *ndst);
566 return MMSYSERR_NOERROR;
569 /***********************************************************************
570 * MPEG3_Reset
573 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
575 AudioConverterReset(aad->acr);
578 /***********************************************************************
579 * MPEG3_StreamOpen
582 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
584 AcmMpeg3Data* aad;
586 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
588 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
589 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
590 return ACMERR_NOTPOSSIBLE;
592 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
593 if (aad == 0) return MMSYSERR_NOMEM;
595 adsi->dwDriver = (DWORD_PTR)aad;
597 if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
598 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
599 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
601 OSStatus err;
603 aad->in.mSampleRate = adsi->pwfxSrc->nSamplesPerSec;
604 aad->out.mSampleRate = adsi->pwfxDst->nSamplesPerSec;
605 aad->in.mBitsPerChannel = adsi->pwfxSrc->wBitsPerSample;
606 aad->out.mBitsPerChannel = adsi->pwfxDst->wBitsPerSample;
607 aad->in.mFormatID = kAudioFormatMPEGLayer3;
608 aad->out.mFormatID = kAudioFormatLinearPCM;
609 aad->in.mChannelsPerFrame = adsi->pwfxSrc->nChannels;
610 aad->out.mChannelsPerFrame = adsi->pwfxDst->nChannels;
611 aad->in.mFormatFlags = 0;
612 aad->out.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
613 aad->in.mBytesPerFrame = 0;
614 aad->out.mBytesPerFrame = (aad->out.mBitsPerChannel * aad->out.mChannelsPerFrame) / 8;
615 aad->in.mBytesPerPacket = 0;
616 aad->out.mBytesPerPacket = aad->out.mBytesPerFrame;
617 aad->in.mFramesPerPacket = 0;
618 aad->out.mFramesPerPacket = 1;
619 aad->in.mReserved = aad->out.mReserved = 0;
621 aad->tagBytesLeft = -1;
623 aad->convert = mp3_leopard_horse;
625 err = AudioConverterNew(&aad->in, &aad->out, &aad->acr);
626 if (err != noErr)
628 ERR("Create failed: %ld\n", err);
630 else
632 MPEG3_Reset(adsi, aad);
634 return MMSYSERR_NOERROR;
638 HeapFree(GetProcessHeap(), 0, aad);
639 adsi->dwDriver = 0;
641 return MMSYSERR_NOTSUPPORTED;
644 /***********************************************************************
645 * MPEG3_StreamClose
648 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
650 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
652 AudioConverterDispose(amd->acr);
654 HeapFree(GetProcessHeap(), 0, amd);
655 adsi->dwDriver = 0;
657 return MMSYSERR_NOERROR;
660 #endif
662 /***********************************************************************
663 * MPEG3_DriverDetails
666 static LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add)
668 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
669 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
670 add->wMid = MM_FRAUNHOFER_IIS;
671 add->wPid = MM_FHGIIS_MPEGLAYER3_DECODE;
672 add->vdwACM = 0x01000000;
673 add->vdwDriver = 0x01000000;
674 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
675 add->cFormatTags = 3; /* PCM, MPEG3 */
676 add->cFilterTags = 0;
677 add->hicon = NULL;
678 MultiByteToWideChar( CP_ACP, 0, "MPEG Layer-3 Codec", -1,
679 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
680 MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1,
681 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
682 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
683 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
684 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
685 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
686 add->szFeatures[0] = 0;
688 return MMSYSERR_NOERROR;
691 /***********************************************************************
692 * MPEG3_FormatTagDetails
695 static LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
697 static const WCHAR szPcm[]={'P','C','M',0};
698 static const WCHAR szMpeg3[]={'M','P','e','g','3',0};
699 static const WCHAR szMpeg[]={'M','P','e','g',0};
701 switch (dwQuery)
703 case ACM_FORMATTAGDETAILSF_INDEX:
704 if (aftd->dwFormatTagIndex > 2) return ACMERR_NOTPOSSIBLE;
705 break;
706 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
707 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
709 aftd->dwFormatTagIndex = 2; /* WAVE_FORMAT_MPEG is biggest */
710 break;
712 /* fall through */
713 case ACM_FORMATTAGDETAILSF_FORMATTAG:
714 switch (aftd->dwFormatTag)
716 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
717 case WAVE_FORMAT_MPEGLAYER3: aftd->dwFormatTagIndex = 1; break;
718 case WAVE_FORMAT_MPEG: aftd->dwFormatTagIndex = 2; break;
719 default: return ACMERR_NOTPOSSIBLE;
721 break;
722 default:
723 WARN("Unsupported query %08x\n", dwQuery);
724 return MMSYSERR_NOTSUPPORTED;
727 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
728 switch (aftd->dwFormatTagIndex)
730 case 0:
731 aftd->dwFormatTag = WAVE_FORMAT_PCM;
732 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
733 aftd->cStandardFormats = NUM_PCM_FORMATS;
734 lstrcpyW(aftd->szFormatTag, szPcm);
735 break;
736 case 1:
737 aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3;
738 aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT);
739 aftd->cStandardFormats = NUM_MPEG3_FORMATS;
740 lstrcpyW(aftd->szFormatTag, szMpeg3);
741 break;
742 case 2:
743 aftd->dwFormatTag = WAVE_FORMAT_MPEG;
744 aftd->cbFormatSize = sizeof(MPEG1WAVEFORMAT);
745 aftd->cStandardFormats = NUM_MPEG3_FORMATS;
746 lstrcpyW(aftd->szFormatTag, szMpeg);
747 break;
749 return MMSYSERR_NOERROR;
752 static void fill_in_mp3(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate)
754 MPEGLAYER3WAVEFORMAT* mp3wfx = (MPEGLAYER3WAVEFORMAT*)wfx;
756 wfx->nAvgBytesPerSec = bit_rate / 8;
757 if (cbwfx >= sizeof(WAVEFORMATEX))
758 wfx->cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
759 if (cbwfx >= sizeof(MPEGLAYER3WAVEFORMAT))
761 mp3wfx->wID = MPEGLAYER3_ID_MPEG;
762 mp3wfx->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
763 mp3wfx->nBlockSize = (bit_rate * 144) / wfx->nSamplesPerSec;
764 mp3wfx->nFramesPerBlock = 1;
765 mp3wfx->nCodecDelay = 0x0571;
769 static void fill_in_mpeg(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate)
771 MPEG1WAVEFORMAT* mp3wfx = (MPEG1WAVEFORMAT*)wfx;
773 wfx->nAvgBytesPerSec = bit_rate / 8;
774 if (cbwfx >= sizeof(WAVEFORMATEX))
775 wfx->cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX);
776 if (cbwfx >= sizeof(MPEG1WAVEFORMAT))
778 mp3wfx->fwHeadLayer = ACM_MPEG_LAYER3;
779 mp3wfx->dwHeadBitrate = wfx->nAvgBytesPerSec * 8;
780 mp3wfx->fwHeadMode = ACM_MPEG_JOINTSTEREO;
781 mp3wfx->fwHeadModeExt = 0xf;
782 mp3wfx->wHeadEmphasis = 1;
783 mp3wfx->fwHeadFlags = ACM_MPEG_ID_MPEG1;
787 /***********************************************************************
788 * MPEG3_FormatDetails
791 static LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
793 switch (dwQuery)
795 case ACM_FORMATDETAILSF_FORMAT:
796 if (MPEG3_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
797 break;
798 case ACM_FORMATDETAILSF_INDEX:
799 afd->pwfx->wFormatTag = afd->dwFormatTag;
800 switch (afd->dwFormatTag)
802 case WAVE_FORMAT_PCM:
803 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
804 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
805 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
806 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
807 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
808 * afd->pwfx->cbSize = 0;
810 afd->pwfx->nBlockAlign =
811 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
812 afd->pwfx->nAvgBytesPerSec =
813 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
814 break;
815 case WAVE_FORMAT_MPEGLAYER3:
816 case WAVE_FORMAT_MPEG:
817 if (afd->dwFormatIndex >= NUM_MPEG3_FORMATS) return ACMERR_NOTPOSSIBLE;
818 afd->pwfx->nChannels = MPEG3_Formats[afd->dwFormatIndex].nChannels;
819 afd->pwfx->nSamplesPerSec = MPEG3_Formats[afd->dwFormatIndex].rate;
820 afd->pwfx->wBitsPerSample = MPEG3_Formats[afd->dwFormatIndex].nBits;
821 afd->pwfx->nBlockAlign = 1;
822 if (afd->dwFormatTag == WAVE_FORMAT_MPEGLAYER3)
823 fill_in_mp3(afd->cbwfx, afd->pwfx, 192000);
824 else
825 fill_in_mpeg(afd->cbwfx, afd->pwfx, 192000);
826 break;
827 default:
828 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
829 return MMSYSERR_INVALPARAM;
831 break;
832 default:
833 WARN("Unsupported query %08x\n", dwQuery);
834 return MMSYSERR_NOTSUPPORTED;
836 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
837 afd->szFormat[0] = 0; /* let MSACM format this for us... */
839 return MMSYSERR_NOERROR;
842 /***********************************************************************
843 * MPEG3_FormatSuggest
846 static LRESULT MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
848 /* some tests ... */
849 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
850 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
851 MPEG3_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
852 /* FIXME: should do those tests against the real size (according to format tag */
854 /* If no suggestion for destination, then copy source value */
855 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
856 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
857 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
858 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
860 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
862 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
863 adfs->pwfxDst->wBitsPerSample = 4;
864 else
865 adfs->pwfxDst->wBitsPerSample = 16;
867 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
869 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
870 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_MPEGLAYER3;
871 else
872 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
875 /* check if result is ok */
876 if (MPEG3_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
878 /* recompute other values */
879 switch (adfs->pwfxDst->wFormatTag)
881 case WAVE_FORMAT_PCM:
882 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
883 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
884 break;
885 case WAVE_FORMAT_MPEG:
886 adfs->pwfxDst->nBlockAlign = 1;
887 fill_in_mpeg(adfs->cbwfxDst, adfs->pwfxDst, 192000);
888 break;
889 case WAVE_FORMAT_MPEGLAYER3:
890 adfs->pwfxDst->nBlockAlign = 1;
891 fill_in_mp3(adfs->cbwfxDst, adfs->pwfxDst, 192000);
892 break;
893 default:
894 FIXME("\n");
895 break;
898 return MMSYSERR_NOERROR;
901 /***********************************************************************
902 * MPEG3_StreamSize
905 static LRESULT MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
907 DWORD nblocks;
909 switch (adss->fdwSize)
911 case ACM_STREAMSIZEF_DESTINATION:
912 /* cbDstLength => cbSrcLength */
913 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
914 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
915 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
917 nblocks = (adss->cbDstLength - 3000) / (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
918 if (nblocks == 0)
919 return ACMERR_NOTPOSSIBLE;
920 adss->cbSrcLength = nblocks * 1152 * adsi->pwfxSrc->nBlockAlign;
922 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
923 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
924 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
926 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * 1152);
927 if (nblocks == 0)
928 return ACMERR_NOTPOSSIBLE;
929 adss->cbSrcLength = nblocks * (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
931 else
933 return MMSYSERR_NOTSUPPORTED;
935 break;
936 case ACM_STREAMSIZEF_SOURCE:
937 /* cbSrcLength => cbDstLength */
938 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
939 (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
940 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
942 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * 1152);
943 if (nblocks == 0)
944 return ACMERR_NOTPOSSIBLE;
945 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nBlockAlign * 1152))
946 /* Round block count up. */
947 nblocks++;
948 adss->cbDstLength = 3000 + nblocks * (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
950 else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
951 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
952 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
954 nblocks = adss->cbSrcLength / (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
955 if (nblocks == 0)
956 return ACMERR_NOTPOSSIBLE;
957 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec))
958 /* Round block count up. */
959 nblocks++;
960 adss->cbDstLength = nblocks * 1152 * adsi->pwfxDst->nBlockAlign;
962 else
964 return MMSYSERR_NOTSUPPORTED;
966 break;
967 default:
968 WARN("Unsupported query %08x\n", adss->fdwSize);
969 return MMSYSERR_NOTSUPPORTED;
971 return MMSYSERR_NOERROR;
974 /***********************************************************************
975 * MPEG3_StreamConvert
978 static LRESULT MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
980 AcmMpeg3Data* aad = (AcmMpeg3Data*)adsi->dwDriver;
981 DWORD nsrc = adsh->cbSrcLength;
982 DWORD ndst = adsh->cbDstLength;
984 if (adsh->fdwConvert &
985 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
986 ACM_STREAMCONVERTF_END|
987 ACM_STREAMCONVERTF_START))
989 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
991 /* ACM_STREAMCONVERTF_BLOCKALIGN
992 * currently all conversions are block aligned, so do nothing for this flag
993 * ACM_STREAMCONVERTF_END
994 * no pending data, so do nothing for this flag
996 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
998 MPEG3_Reset(adsi, aad);
1001 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
1002 adsh->cbSrcLengthUsed = nsrc;
1003 adsh->cbDstLengthUsed = ndst;
1005 return MMSYSERR_NOERROR;
1008 /**************************************************************************
1009 * MPEG3_DriverProc [exported]
1011 LRESULT CALLBACK MPEG3_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1012 LPARAM dwParam1, LPARAM dwParam2)
1014 TRACE("(%08lx %p %04x %08lx %08lx);\n",
1015 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1017 switch (wMsg)
1019 case DRV_LOAD: return 1;
1020 case DRV_FREE: return 1;
1021 case DRV_OPEN: return MPEG3_drvOpen((LPSTR)dwParam1);
1022 case DRV_CLOSE: return MPEG3_drvClose(dwDevID);
1023 case DRV_ENABLE: return 1;
1024 case DRV_DISABLE: return 1;
1025 case DRV_QUERYCONFIGURE: return 1;
1026 case DRV_CONFIGURE: MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK); return 1;
1027 case DRV_INSTALL: return DRVCNF_RESTART;
1028 case DRV_REMOVE: return DRVCNF_RESTART;
1030 case ACMDM_DRIVER_NOTIFY:
1031 /* no caching from other ACM drivers is done so far */
1032 return MMSYSERR_NOERROR;
1034 case ACMDM_DRIVER_DETAILS:
1035 return MPEG3_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
1037 case ACMDM_FORMATTAG_DETAILS:
1038 return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
1040 case ACMDM_FORMAT_DETAILS:
1041 return MPEG3_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
1043 case ACMDM_FORMAT_SUGGEST:
1044 return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
1046 case ACMDM_STREAM_OPEN:
1047 return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
1049 case ACMDM_STREAM_CLOSE:
1050 return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1052 case ACMDM_STREAM_SIZE:
1053 return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1055 case ACMDM_STREAM_CONVERT:
1056 return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1058 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1059 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1060 /* this converter is not a hardware driver */
1061 case ACMDM_FILTERTAG_DETAILS:
1062 case ACMDM_FILTER_DETAILS:
1063 /* this converter is not a filter */
1064 case ACMDM_STREAM_RESET:
1065 /* only needed for asynchronous driver... we aren't, so just say it */
1066 return MMSYSERR_NOTSUPPORTED;
1067 case ACMDM_STREAM_PREPARE:
1068 case ACMDM_STREAM_UNPREPARE:
1069 /* nothing special to do here... so don't do anything */
1070 return MMSYSERR_NOERROR;
1072 default:
1073 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);