winex11: Set window style to normal for windows with a minimize box.
[wine/hramrach.git] / dlls / winemp3.acm / mpegl3.c
blob92a3afc2ed34ffb52e9e8a4846ca4c75b725b9cf
1 /*
2 * MPEG Layer 3 handling
4 * Copyright (C) 2002 Eric Pouech
5 * Copyright (C) 2009 CodeWeavers, Aric Stewart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <assert.h>
27 #include <stdarg.h>
28 #include <string.h>
30 #ifdef HAVE_MPG123_H
31 # include <mpg123.h>
32 #else
33 # ifdef HAVE_COREAUDIO_COREAUDIO_H
34 # include <CoreFoundation/CoreFoundation.h>
35 # include <CoreAudio/CoreAudio.h>
36 # endif
37 # ifdef HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H
38 # include <AudioToolbox/AudioConverter.h>
39 # endif
40 #endif
42 #include "windef.h"
43 #include "winbase.h"
44 #include "wingdi.h"
45 #include "winuser.h"
46 #include "winnls.h"
47 #include "mmsystem.h"
48 #include "mmreg.h"
49 #include "msacm.h"
50 #include "msacmdrv.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(mpeg3);
55 /* table to list all supported formats... those are the basic ones. this
56 * also helps given a unique index to each of the supported formats
58 typedef struct
60 int nChannels;
61 int nBits;
62 int rate;
63 } Format;
65 static const Format PCM_Formats[] =
67 {1, 8, 8000}, {2, 8, 8000}, {1, 16, 8000}, {2, 16, 8000},
68 {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025},
69 {1, 8, 12000}, {2, 8, 12000}, {1, 16, 12000}, {2, 16, 12000},
70 {1, 8, 16000}, {2, 8, 16000}, {1, 16, 16000}, {2, 16, 16000},
71 {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050},
72 {1, 8, 24000}, {2, 8, 24000}, {1, 16, 24000}, {2, 16, 24000},
73 {1, 8, 32000}, {2, 8, 32000}, {1, 16, 32000}, {2, 16, 32000},
74 {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100},
75 {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}
78 static const Format MPEG3_Formats[] =
80 {1, 0, 8000}, {2, 0, 8000},
81 {1, 0, 11025}, {2, 0, 11025},
82 {1, 0, 12000}, {2, 0, 12000},
83 {1, 0, 16000}, {2, 0, 16000},
84 {1, 0, 22050}, {2, 0, 22050},
85 {1, 0, 24000}, {2, 0, 24000},
86 {1, 0, 32000}, {2, 0, 32000},
87 {1, 0, 44100}, {2, 0, 44100},
88 {1, 0, 48000}, {2, 0, 48000}
91 #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0]))
92 #define NUM_MPEG3_FORMATS (sizeof(MPEG3_Formats) / sizeof(MPEG3_Formats[0]))
94 /***********************************************************************
95 * MPEG3_GetFormatIndex
97 static DWORD MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx)
99 int i, hi;
100 const Format *fmts;
102 switch (wfx->wFormatTag)
104 case WAVE_FORMAT_PCM:
105 hi = NUM_PCM_FORMATS;
106 fmts = PCM_Formats;
107 break;
108 case WAVE_FORMAT_MPEGLAYER3:
109 hi = NUM_MPEG3_FORMATS;
110 fmts = MPEG3_Formats;
111 break;
112 default:
113 return 0xFFFFFFFF;
116 for (i = 0; i < hi; i++)
118 if (wfx->nChannels == fmts[i].nChannels &&
119 wfx->nSamplesPerSec == fmts[i].rate &&
120 (wfx->wBitsPerSample == fmts[i].nBits || !fmts[i].nBits))
121 return i;
124 return 0xFFFFFFFF;
127 #ifdef HAVE_MPG123_H
129 typedef struct tagAcmMpeg3Data
131 void (*convert)(PACMDRVSTREAMINSTANCE adsi,
132 const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
133 mpg123_handle *mh;
134 } AcmMpeg3Data;
136 /***********************************************************************
137 * MPEG3_drvOpen
139 static LRESULT MPEG3_drvOpen(LPCSTR str)
141 mpg123_init();
142 return 1;
145 /***********************************************************************
146 * MPEG3_drvClose
148 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
150 mpg123_exit();
151 return 1;
155 static void mp3_horse(PACMDRVSTREAMINSTANCE adsi,
156 const unsigned char* src, LPDWORD nsrc,
157 unsigned char* dst, LPDWORD ndst)
159 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
160 int ret;
161 size_t size;
162 DWORD dpos = 0;
165 if (*nsrc > 0)
167 ret = mpg123_feed(amd->mh, src, *nsrc);
168 if (ret != MPG123_OK)
170 ERR("Error feeding data\n");
171 *ndst = *nsrc = 0;
172 return;
176 do {
177 size = 0;
178 ret = mpg123_read(amd->mh, dst + dpos, *ndst - dpos, &size);
179 if (ret == MPG123_ERR)
181 FIXME("Error occurred during decoding!\n");
182 *ndst = *nsrc = 0;
183 return;
186 if (ret == MPG123_NEW_FORMAT)
188 long rate;
189 int channels, enc;
190 mpg123_getformat(amd->mh, &rate, &channels, &enc);
191 TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
193 dpos += size;
194 if (dpos > *ndst) break;
195 } while (ret != MPG123_ERR && ret != MPG123_NEED_MORE);
196 *ndst = dpos;
199 /***********************************************************************
200 * MPEG3_Reset
203 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
205 mpg123_feedseek(aad->mh, 0, SEEK_SET, NULL);
206 mpg123_close(aad->mh);
207 mpg123_open_feed(aad->mh);
210 /***********************************************************************
211 * MPEG3_StreamOpen
214 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
216 AcmMpeg3Data* aad;
217 int err;
219 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
221 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
222 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
223 return ACMERR_NOTPOSSIBLE;
225 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
226 if (aad == 0) return MMSYSERR_NOMEM;
228 adsi->dwDriver = (DWORD_PTR)aad;
230 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
231 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
233 goto theEnd;
235 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 &&
236 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
238 /* resampling or mono <=> stereo not available
239 * MPEG3 algo only define 16 bit per sample output
241 if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
242 adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
243 adsi->pwfxDst->wBitsPerSample != 16)
244 goto theEnd;
245 aad->convert = mp3_horse;
246 aad->mh = mpg123_new(NULL,&err);
247 mpg123_open_feed(aad->mh);
249 /* no encoding yet
250 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
251 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
253 else goto theEnd;
254 MPEG3_Reset(adsi, aad);
256 return MMSYSERR_NOERROR;
258 theEnd:
259 HeapFree(GetProcessHeap(), 0, aad);
260 adsi->dwDriver = 0L;
261 return MMSYSERR_NOTSUPPORTED;
264 /***********************************************************************
265 * MPEG3_StreamClose
268 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
270 mpg123_close(((AcmMpeg3Data*)adsi->dwDriver)->mh);
271 mpg123_delete(((AcmMpeg3Data*)adsi->dwDriver)->mh);
272 HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
273 return MMSYSERR_NOERROR;
276 #elif defined(HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H)
278 static const unsigned short Mp3BitRates[2][16] =
280 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
281 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
284 static const unsigned short Mp3SampleRates[2][4] =
286 {44100, 48000, 32000, 0},
287 {22050, 24000, 16000, 0}
290 typedef struct tagAcmMpeg3Data
292 LRESULT (*convert)(PACMDRVSTREAMINSTANCE adsi, const unsigned char*,
293 LPDWORD, unsigned char*, LPDWORD);
294 AudioConverterRef acr;
295 AudioStreamBasicDescription in,out;
297 AudioBufferList outBuffer;
298 AudioBuffer inBuffer;
300 SInt32 tagBytesLeft;
302 UInt32 NumberPackets;
303 AudioStreamPacketDescription *PacketDescriptions;
304 } AcmMpeg3Data;
306 /***********************************************************************
307 * MPEG3_drvOpen
309 static LRESULT MPEG3_drvOpen(LPCSTR str)
311 return 1;
314 /***********************************************************************
315 * MPEG3_drvClose
317 static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
319 return 1;
323 When it asks for data, give it all we have. If we have no data, we assume
324 we will in the future, so give it no packets and return an error, which
325 signals that we will have more later.
327 static OSStatus Mp3AudioConverterComplexInputDataProc(
328 AudioConverterRef inAudioConverter,
329 UInt32 *ioNumberDataPackets,
330 AudioBufferList *ioData,
331 AudioStreamPacketDescription **outDataPacketDescription,
332 void *inUserData
335 AcmMpeg3Data *amd = (AcmMpeg3Data*)inUserData;
337 if (amd->inBuffer.mDataByteSize > 0)
339 *ioNumberDataPackets = amd->NumberPackets;
340 ioData->mNumberBuffers = 1;
341 ioData->mBuffers[0] = amd->inBuffer;
342 amd->inBuffer.mDataByteSize = 0;
343 if (outDataPacketDescription)
344 *outDataPacketDescription = amd->PacketDescriptions;
345 return noErr;
347 else
349 *ioNumberDataPackets = 0;
350 return -74;
355 Get the length of the current frame. We need to be at the start of a
356 frame now. The buffer must have at least the four bytes for the header.
358 static SInt32 Mp3GetPacketLength(const unsigned char* src)
360 unsigned char mpegv;
361 unsigned short brate, srate;
362 unsigned int size;
365 Check that our position looks like an MP3 header and see which type
366 of MP3 file we have.
368 if (src[0] == 0xff && src[1] >> 1 == 0x7d) mpegv = 0; /* MPEG-1 File */
369 else if (src[0] == 0xff && src[1] >> 1 == 0x79) mpegv = 1; /* MPEG-2 File */
370 else return -1;
372 /* Fill in bit rate and sample rate. */
373 brate = Mp3BitRates[mpegv][(src[2] & 0xf0) >> 4];
374 srate = Mp3SampleRates[mpegv][(src[2] & 0xc) >> 2];
376 /* Certain values for bit rate and sample rate are invalid. */
377 if (brate == 0 || srate == 0) return -1;
379 /* Compute frame size, round down */
380 size = 72 * (2 - mpegv) * brate * 1000 / srate;
382 /* If there is padding, add one byte */
383 if (src[2] & 0x2) return size + 1;
384 else return size;
388 Apple's AudioFileStream does weird things so we deal with parsing the
389 file ourselves. It was also designed for a different use case, so this
390 is not unexpected. We expect to have MP3 data as input (i.e. we can only
391 deal with MPEG-1 or MPEG-2 Layer III), which simplifies parsing a bit. We
392 understand the ID3v2 header and skip over it. Whenever we have data we
393 want to skip at the beginning of the input, we do this by setting *ndst=0
394 and *nsrc to the length of the unwanted data and return no error.
396 static LRESULT mp3_leopard_horse(PACMDRVSTREAMINSTANCE adsi,
397 const unsigned char* src, LPDWORD nsrc,
398 unsigned char* dst, LPDWORD ndst)
400 OSStatus err;
401 UInt32 size, aspdi, synci, syncSkip;
402 short framelen[4];
403 const unsigned char* psrc;
404 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
406 TRACE("ndst %u %p <- %u %p\n", *ndst, dst, *nsrc, src);
408 TRACE("First 16 bytes to input: %s\n", wine_dbgstr_an(src, 16));
410 /* Parse ID3 tag */
411 if (!memcmp(src, "ID3", 3) && amd->tagBytesLeft == -1)
413 amd->tagBytesLeft = (src[6] << 21) + (src[7] << 14) + (src[8] << 7) + src[9];
414 if (src[5] & 0x10) amd->tagBytesLeft += 20; /* There is a footer */
415 else amd->tagBytesLeft += 10;
418 /* Consume the tag */
419 if (amd->tagBytesLeft >= (SInt32)*nsrc)
421 *ndst = 0;
422 amd->tagBytesLeft -= *nsrc;
424 TRACE("All %d bytes of source data is ID3 tag\n", *nsrc);
425 return MMSYSERR_NOERROR;
427 else if (amd->tagBytesLeft > 0)
429 src += amd->tagBytesLeft;
430 *nsrc -= amd->tagBytesLeft;
431 TRACE("Skipping %d for ID3 tag\n", amd->tagBytesLeft);
435 Sync to initial MP3 frame. The largest possible MP3 frame is 1440.
436 Thus, in the first 1440 bytes we must find the beginning of 3 valid
437 frames in a row unless we reach the end of the file first.
439 syncSkip = 0;
440 for (psrc = src; psrc <= src + *nsrc - 4 && psrc < src + 1440; psrc++)
442 framelen[0] = 0;
443 for (synci = 1;
444 synci < 4 && psrc + framelen[synci-1] < src + *nsrc - 4;
445 synci++)
447 framelen[synci] = Mp3GetPacketLength(psrc + framelen[synci-1]);
448 if (framelen[synci] == -1)
450 synci = 0;
451 break;
453 framelen[synci] += framelen[synci-1];
455 if (synci > 0) /* We synced successfully */
457 if (psrc - src > 0)
459 syncSkip = psrc - src;
460 src += syncSkip;
461 *nsrc -= syncSkip;
462 TRACE("Skipping %d for frame sync\n", syncSkip);
464 break;
468 if (Mp3GetPacketLength(src) == -1)
470 *ndst = *nsrc = 0;
471 ERR("Frame sync failed. Cannot play file.\n");
472 return MMSYSERR_ERROR;
476 Fill in frame descriptions for all frames. We use an extra pointer
477 to keep track of our position in the input.
480 amd->NumberPackets = 25; /* This is the initial array capacity */
481 amd->PacketDescriptions = HeapAlloc(GetProcessHeap(), 0, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
482 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
484 for (aspdi = 0, psrc = src;
485 psrc <= src + *nsrc - 4;
486 psrc += amd->PacketDescriptions[aspdi].mDataByteSize, aspdi++)
488 /* Return an error if we can't read the frame header */
489 if (Mp3GetPacketLength(psrc) == -1)
491 *ndst = *nsrc = 0;
492 ERR("Invalid header at %p.\n", psrc);
493 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
494 return MMSYSERR_ERROR;
497 /* If we run out of space, double size and reallocate */
498 if (aspdi >= amd->NumberPackets)
500 amd->NumberPackets *= 2;
501 amd->PacketDescriptions = HeapReAlloc(GetProcessHeap(), 0, amd->PacketDescriptions, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
502 if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
505 /* Fill in packet data */
506 amd->PacketDescriptions[aspdi].mStartOffset = psrc - src;
507 amd->PacketDescriptions[aspdi].mVariableFramesInPacket = 0;
508 amd->PacketDescriptions[aspdi].mDataByteSize = Mp3GetPacketLength(psrc);
510 /* If this brings us past the end, the last one doesn't count */
511 if (psrc + amd->PacketDescriptions[aspdi].mDataByteSize > src + *nsrc) break;
514 /* Fill in correct number of frames */
515 amd->NumberPackets = aspdi;
517 /* Adjust nsrc to only include full frames */
518 *nsrc = psrc - src;
520 amd->inBuffer.mDataByteSize = *nsrc;
521 amd->inBuffer.mData = src;
522 amd->inBuffer.mNumberChannels = amd->in.mChannelsPerFrame;
524 amd->outBuffer.mNumberBuffers = 1;
525 amd->outBuffer.mBuffers[0].mDataByteSize = *ndst;
526 amd->outBuffer.mBuffers[0].mData = dst;
527 amd->outBuffer.mBuffers[0].mNumberChannels = amd->out.mChannelsPerFrame;
529 /* Convert the data */
530 size = amd->outBuffer.mBuffers[0].mDataByteSize / amd->out.mBytesPerPacket;
531 err = AudioConverterFillComplexBuffer(amd->acr, Mp3AudioConverterComplexInputDataProc, amd, &size, &amd->outBuffer, 0);
533 HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
535 /* Add skipped bytes back into *nsrc */
536 if (amd->tagBytesLeft > 0)
538 *nsrc += amd->tagBytesLeft;
539 amd->tagBytesLeft = 0;
541 *nsrc += syncSkip;
543 if (err != noErr && err != -74)
545 *ndst = *nsrc = 0;
546 ERR("Feed Error: %ld\n", err);
547 return MMSYSERR_ERROR;
550 *ndst = amd->outBuffer.mBuffers[0].mDataByteSize;
552 TRACE("convert %d -> %d\n", *nsrc, *ndst);
554 return MMSYSERR_NOERROR;
557 /***********************************************************************
558 * MPEG3_Reset
561 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
563 AudioConverterReset(aad->acr);
566 /***********************************************************************
567 * MPEG3_StreamOpen
570 static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
572 AcmMpeg3Data* aad;
574 assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));
576 if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
577 MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
578 return ACMERR_NOTPOSSIBLE;
580 aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
581 if (aad == 0) return MMSYSERR_NOMEM;
583 adsi->dwDriver = (DWORD_PTR)aad;
585 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 &&
586 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
588 OSStatus err;
590 aad->in.mSampleRate = adsi->pwfxSrc->nSamplesPerSec;
591 aad->out.mSampleRate = adsi->pwfxDst->nSamplesPerSec;
592 aad->in.mBitsPerChannel = adsi->pwfxSrc->wBitsPerSample;
593 aad->out.mBitsPerChannel = adsi->pwfxDst->wBitsPerSample;
594 aad->in.mFormatID = kAudioFormatMPEGLayer3;
595 aad->out.mFormatID = kAudioFormatLinearPCM;
596 aad->in.mChannelsPerFrame = adsi->pwfxSrc->nChannels;
597 aad->out.mChannelsPerFrame = adsi->pwfxDst->nChannels;
598 aad->in.mFormatFlags = 0;
599 aad->out.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
600 aad->in.mBytesPerFrame = 0;
601 aad->out.mBytesPerFrame = (aad->out.mBitsPerChannel * aad->out.mChannelsPerFrame) / 8;
602 aad->in.mBytesPerPacket = 0;
603 aad->out.mBytesPerPacket = aad->out.mBytesPerFrame;
604 aad->in.mFramesPerPacket = 0;
605 aad->out.mFramesPerPacket = 1;
606 aad->in.mReserved = aad->out.mReserved = 0;
608 aad->tagBytesLeft = -1;
610 aad->convert = mp3_leopard_horse;
612 err = AudioConverterNew(&aad->in, &aad->out, &aad->acr);
613 if (err != noErr)
615 ERR("Create failed: %ld\n", err);
617 else
619 MPEG3_Reset(adsi, aad);
621 return MMSYSERR_NOERROR;
625 HeapFree(GetProcessHeap(), 0, aad);
626 adsi->dwDriver = 0;
628 return MMSYSERR_NOTSUPPORTED;
631 /***********************************************************************
632 * MPEG3_StreamClose
635 static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
637 AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;
639 AudioConverterDispose(amd->acr);
641 HeapFree(GetProcessHeap(), 0, amd);
642 adsi->dwDriver = 0;
644 return MMSYSERR_NOERROR;
647 #endif
649 /***********************************************************************
650 * MPEG3_DriverDetails
653 static LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add)
655 add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
656 add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
657 add->wMid = 0xFF;
658 add->wPid = 0x00;
659 add->vdwACM = 0x01000000;
660 add->vdwDriver = 0x01000000;
661 add->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
662 add->cFormatTags = 2; /* PCM, MPEG3 */
663 add->cFilterTags = 0;
664 add->hicon = NULL;
665 MultiByteToWideChar( CP_ACP, 0, "WINE-MPEG3", -1,
666 add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
667 MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1,
668 add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
669 MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
670 add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
671 MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
672 add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
673 add->szFeatures[0] = 0;
675 return MMSYSERR_NOERROR;
678 /***********************************************************************
679 * MPEG3_FormatTagDetails
682 static LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
684 static const WCHAR szPcm[]={'P','C','M',0};
685 static const WCHAR szMpeg3[]={'M','P','e','g','3',0};
687 switch (dwQuery)
689 case ACM_FORMATTAGDETAILSF_INDEX:
690 if (aftd->dwFormatTagIndex >= 2) return ACMERR_NOTPOSSIBLE;
691 break;
692 case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
693 if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
695 aftd->dwFormatTagIndex = 1; /* WAVE_FORMAT_MPEGLAYER3 is bigger than PCM */
696 break;
698 /* fall thru */
699 case ACM_FORMATTAGDETAILSF_FORMATTAG:
700 switch (aftd->dwFormatTag)
702 case WAVE_FORMAT_PCM: aftd->dwFormatTagIndex = 0; break;
703 case WAVE_FORMAT_MPEGLAYER3: aftd->dwFormatTagIndex = 1; break;
704 default: return ACMERR_NOTPOSSIBLE;
706 break;
707 default:
708 WARN("Unsupported query %08x\n", dwQuery);
709 return MMSYSERR_NOTSUPPORTED;
712 aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
713 switch (aftd->dwFormatTagIndex)
715 case 0:
716 aftd->dwFormatTag = WAVE_FORMAT_PCM;
717 aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
718 aftd->cStandardFormats = NUM_PCM_FORMATS;
719 lstrcpyW(aftd->szFormatTag, szPcm);
720 break;
721 case 1:
722 aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3;
723 aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT);
724 aftd->cStandardFormats = NUM_MPEG3_FORMATS;
725 lstrcpyW(aftd->szFormatTag, szMpeg3);
726 break;
728 return MMSYSERR_NOERROR;
731 static void fill_in_wfx(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate)
733 MPEGLAYER3WAVEFORMAT* mp3wfx = (MPEGLAYER3WAVEFORMAT*)wfx;
735 wfx->nAvgBytesPerSec = bit_rate / 8;
736 if (cbwfx >= sizeof(WAVEFORMATEX))
737 wfx->cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
738 if (cbwfx >= sizeof(MPEGLAYER3WAVEFORMAT))
740 mp3wfx->wID = MPEGLAYER3_ID_MPEG;
741 mp3wfx->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
742 mp3wfx->nBlockSize = (bit_rate * 144) / wfx->nSamplesPerSec;
743 mp3wfx->nFramesPerBlock = 1;
744 mp3wfx->nCodecDelay = 0x0571;
748 /***********************************************************************
749 * MPEG3_FormatDetails
752 static LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
754 switch (dwQuery)
756 case ACM_FORMATDETAILSF_FORMAT:
757 if (MPEG3_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
758 break;
759 case ACM_FORMATDETAILSF_INDEX:
760 afd->pwfx->wFormatTag = afd->dwFormatTag;
761 switch (afd->dwFormatTag)
763 case WAVE_FORMAT_PCM:
764 if (afd->dwFormatIndex >= NUM_PCM_FORMATS) return ACMERR_NOTPOSSIBLE;
765 afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
766 afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
767 afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
768 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
769 * afd->pwfx->cbSize = 0;
771 afd->pwfx->nBlockAlign =
772 (afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
773 afd->pwfx->nAvgBytesPerSec =
774 afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
775 break;
776 case WAVE_FORMAT_MPEGLAYER3:
777 if (afd->dwFormatIndex >= NUM_MPEG3_FORMATS) return ACMERR_NOTPOSSIBLE;
778 afd->pwfx->nChannels = MPEG3_Formats[afd->dwFormatIndex].nChannels;
779 afd->pwfx->nSamplesPerSec = MPEG3_Formats[afd->dwFormatIndex].rate;
780 afd->pwfx->wBitsPerSample = MPEG3_Formats[afd->dwFormatIndex].nBits;
781 afd->pwfx->nBlockAlign = 1;
782 fill_in_wfx(afd->cbwfx, afd->pwfx, 192000);
783 break;
784 default:
785 WARN("Unsupported tag %08x\n", afd->dwFormatTag);
786 return MMSYSERR_INVALPARAM;
788 break;
789 default:
790 WARN("Unsupported query %08x\n", dwQuery);
791 return MMSYSERR_NOTSUPPORTED;
793 afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
794 afd->szFormat[0] = 0; /* let MSACM format this for us... */
796 return MMSYSERR_NOERROR;
799 /***********************************************************************
800 * MPEG3_FormatSuggest
803 static LRESULT MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
805 /* some tests ... */
806 if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
807 adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
808 MPEG3_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
809 /* FIXME: should do those tests against the real size (according to format tag */
811 /* If no suggestion for destination, then copy source value */
812 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
813 adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
814 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
815 adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
817 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
819 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
820 adfs->pwfxDst->wBitsPerSample = 4;
821 else
822 adfs->pwfxDst->wBitsPerSample = 16;
824 if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
826 if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
827 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_MPEGLAYER3;
828 else
829 adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
832 /* check if result is ok */
833 if (MPEG3_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
835 /* recompute other values */
836 switch (adfs->pwfxDst->wFormatTag)
838 case WAVE_FORMAT_PCM:
839 adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
840 adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
841 break;
842 case WAVE_FORMAT_MPEGLAYER3:
843 adfs->pwfxDst->nBlockAlign = 1;
844 fill_in_wfx(adfs->cbwfxDst, adfs->pwfxDst, 192000);
845 break;
846 default:
847 FIXME("\n");
848 break;
851 return MMSYSERR_NOERROR;
854 /***********************************************************************
855 * MPEG3_StreamSize
858 static LRESULT MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
860 DWORD nblocks;
862 switch (adss->fdwSize)
864 case ACM_STREAMSIZEF_DESTINATION:
865 /* cbDstLength => cbSrcLength */
866 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
867 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
869 nblocks = (adss->cbDstLength - 3000) / (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
870 if (nblocks == 0)
871 return ACMERR_NOTPOSSIBLE;
872 adss->cbSrcLength = nblocks * 1152 * adsi->pwfxSrc->nBlockAlign;
874 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 &&
875 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
877 nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * 1152);
878 if (nblocks == 0)
879 return ACMERR_NOTPOSSIBLE;
880 adss->cbSrcLength = nblocks * (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
882 else
884 return MMSYSERR_NOTSUPPORTED;
886 break;
887 case ACM_STREAMSIZEF_SOURCE:
888 /* cbSrcLength => cbDstLength */
889 if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
890 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
892 nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * 1152);
893 if (nblocks == 0)
894 return ACMERR_NOTPOSSIBLE;
895 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nBlockAlign * 1152))
896 /* Round block count up. */
897 nblocks++;
898 adss->cbDstLength = 3000 + nblocks * (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
900 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 &&
901 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
903 nblocks = adss->cbSrcLength / (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
904 if (nblocks == 0)
905 return ACMERR_NOTPOSSIBLE;
906 if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec))
907 /* Round block count up. */
908 nblocks++;
909 adss->cbDstLength = nblocks * 1152 * adsi->pwfxDst->nBlockAlign;
911 else
913 return MMSYSERR_NOTSUPPORTED;
915 break;
916 default:
917 WARN("Unsupported query %08x\n", adss->fdwSize);
918 return MMSYSERR_NOTSUPPORTED;
920 return MMSYSERR_NOERROR;
923 /***********************************************************************
924 * MPEG3_StreamConvert
927 static LRESULT MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
929 AcmMpeg3Data* aad = (AcmMpeg3Data*)adsi->dwDriver;
930 DWORD nsrc = adsh->cbSrcLength;
931 DWORD ndst = adsh->cbDstLength;
933 if (adsh->fdwConvert &
934 ~(ACM_STREAMCONVERTF_BLOCKALIGN|
935 ACM_STREAMCONVERTF_END|
936 ACM_STREAMCONVERTF_START))
938 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
940 /* ACM_STREAMCONVERTF_BLOCKALIGN
941 * currently all conversions are block aligned, so do nothing for this flag
942 * ACM_STREAMCONVERTF_END
943 * no pending data, so do nothing for this flag
945 if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
947 MPEG3_Reset(adsi, aad);
950 aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
951 adsh->cbSrcLengthUsed = nsrc;
952 adsh->cbDstLengthUsed = ndst;
954 return MMSYSERR_NOERROR;
957 /**************************************************************************
958 * MPEG3_DriverProc [exported]
960 LRESULT CALLBACK MPEG3_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
961 LPARAM dwParam1, LPARAM dwParam2)
963 TRACE("(%08lx %p %04x %08lx %08lx);\n",
964 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
966 switch (wMsg)
968 case DRV_LOAD: return 1;
969 case DRV_FREE: return 1;
970 case DRV_OPEN: return MPEG3_drvOpen((LPSTR)dwParam1);
971 case DRV_CLOSE: return MPEG3_drvClose(dwDevID);
972 case DRV_ENABLE: return 1;
973 case DRV_DISABLE: return 1;
974 case DRV_QUERYCONFIGURE: return 1;
975 case DRV_CONFIGURE: MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK); return 1;
976 case DRV_INSTALL: return DRVCNF_RESTART;
977 case DRV_REMOVE: return DRVCNF_RESTART;
979 case ACMDM_DRIVER_NOTIFY:
980 /* no caching from other ACM drivers is done so far */
981 return MMSYSERR_NOERROR;
983 case ACMDM_DRIVER_DETAILS:
984 return MPEG3_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
986 case ACMDM_FORMATTAG_DETAILS:
987 return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
989 case ACMDM_FORMAT_DETAILS:
990 return MPEG3_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
992 case ACMDM_FORMAT_SUGGEST:
993 return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
995 case ACMDM_STREAM_OPEN:
996 return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
998 case ACMDM_STREAM_CLOSE:
999 return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1001 case ACMDM_STREAM_SIZE:
1002 return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1004 case ACMDM_STREAM_CONVERT:
1005 return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1007 case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
1008 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
1009 /* this converter is not a hardware driver */
1010 case ACMDM_FILTERTAG_DETAILS:
1011 case ACMDM_FILTER_DETAILS:
1012 /* this converter is not a filter */
1013 case ACMDM_STREAM_RESET:
1014 /* only needed for asynchronous driver... we aren't, so just say it */
1015 return MMSYSERR_NOTSUPPORTED;
1016 case ACMDM_STREAM_PREPARE:
1017 case ACMDM_STREAM_UNPREPARE:
1018 /* nothing special to do here... so don't do anything */
1019 return MMSYSERR_NOERROR;
1021 default:
1022 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);