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
25 //#include "wine/port.h"
34 # ifdef HAVE_COREAUDIO_COREAUDIO_H
35 # include <CoreFoundation/CoreFoundation.h>
36 # include <CoreAudio/CoreAudio.h>
38 # ifdef HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H
39 # include <AudioToolbox/AudioConverter.h>
48 //#include "mmsystem.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
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
)
103 switch (wfx
->wFormatTag
)
105 case WAVE_FORMAT_PCM
:
106 hi
= NUM_PCM_FORMATS
;
109 case WAVE_FORMAT_MPEG
:
110 case WAVE_FORMAT_MPEGLAYER3
:
111 hi
= NUM_MPEG3_FORMATS
;
112 fmts
= MPEG3_Formats
;
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
))
131 typedef struct tagAcmMpeg3Data
133 void (*convert
)(PACMDRVSTREAMINSTANCE adsi
,
134 const unsigned char*, LPDWORD
, unsigned char*, LPDWORD
);
138 /***********************************************************************
141 static LRESULT
MPEG3_drvOpen(LPCSTR str
)
147 /***********************************************************************
150 static LRESULT
MPEG3_drvClose(DWORD_PTR dwDevID
)
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
;
169 ret
= mpg123_feed(amd
->mh
, src
, *nsrc
);
170 if (ret
!= MPG123_OK
)
172 ERR("Error feeding data\n");
180 ret
= mpg123_read(amd
->mh
, dst
+ dpos
, *ndst
- dpos
, &size
);
181 if (ret
== MPG123_ERR
)
183 FIXME("Error occurred during decoding!\n");
188 if (ret
== MPG123_NEW_FORMAT
)
192 mpg123_getformat(amd
->mh
, &rate
, &channels
, &enc
);
193 TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate
, channels
, enc
);
196 if (dpos
>= *ndst
) break;
197 } while (ret
!= MPG123_ERR
&& ret
!= MPG123_NEED_MORE
);
201 /***********************************************************************
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 /***********************************************************************
216 static LRESULT
MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi
)
218 LRESULT error
= MMSYSERR_NOTSUPPORTED
;
222 assert(!(adsi
->fdwOpen
& ACM_STREAMOPENF_ASYNC
));
224 if (MPEG3_GetFormatIndex(adsi
->pwfxSrc
) == 0xFFFFFFFF ||
225 MPEG3_GetFormatIndex(adsi
->pwfxDst
) == 0xFFFFFFFF)
226 return ACMERR_NOTPOSSIBLE
;
228 aad
= HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data
));
229 if (aad
== 0) return MMSYSERR_NOMEM
;
231 adsi
->dwDriver
= (DWORD_PTR
)aad
;
233 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
234 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
238 else if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
||
239 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEG
) &&
240 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
242 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
)
244 MPEGLAYER3WAVEFORMAT
*formatmp3
= (MPEGLAYER3WAVEFORMAT
*)adsi
->pwfxSrc
;
246 if (adsi
->pwfxSrc
->cbSize
< MPEGLAYER3_WFX_EXTRA_BYTES
||
247 formatmp3
->wID
!= MPEGLAYER3_ID_MPEG
)
249 error
= ACMERR_NOTPOSSIBLE
;
254 /* resampling or mono <=> stereo not available
255 * MPEG3 algo only define 16 bit per sample output
257 if (adsi
->pwfxSrc
->nSamplesPerSec
!= adsi
->pwfxDst
->nSamplesPerSec
||
258 adsi
->pwfxSrc
->nChannels
!= adsi
->pwfxDst
->nChannels
||
259 adsi
->pwfxDst
->wBitsPerSample
!= 16)
261 aad
->convert
= mp3_horse
;
262 aad
->mh
= mpg123_new(NULL
,&err
);
263 mpg123_open_feed(aad
->mh
);
265 #if MPG123_API_VERSION >= 31 /* needed for MPG123_IGNORE_FRAMEINFO enum value */
266 /* mpg123 may find a XING header in the mp3 and use that information
267 * to ask for seeks in order to read specific frames in the file.
268 * We cannot allow that since the caller application is feeding us.
269 * This fixes problems for mp3 files encoded with LAME (bug 42361)
271 mpg123_param(aad
->mh
, MPG123_ADD_FLAGS
, MPG123_IGNORE_INFOFRAME
, 0);
275 else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
276 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
279 MPEG3_Reset(adsi
, aad
);
281 return MMSYSERR_NOERROR
;
284 HeapFree(GetProcessHeap(), 0, aad
);
289 /***********************************************************************
293 static LRESULT
MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi
)
295 mpg123_close(((AcmMpeg3Data
*)adsi
->dwDriver
)->mh
);
296 mpg123_delete(((AcmMpeg3Data
*)adsi
->dwDriver
)->mh
);
297 HeapFree(GetProcessHeap(), 0, (void*)adsi
->dwDriver
);
298 return MMSYSERR_NOERROR
;
301 #elif defined(HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H)
303 static const unsigned short Mp3BitRates
[2][16] =
305 {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
306 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
309 static const unsigned short Mp3SampleRates
[2][4] =
311 {44100, 48000, 32000, 0},
312 {22050, 24000, 16000, 0}
315 typedef struct tagAcmMpeg3Data
317 LRESULT (*convert
)(PACMDRVSTREAMINSTANCE adsi
, unsigned char*,
318 LPDWORD
, unsigned char*, LPDWORD
);
319 AudioConverterRef acr
;
320 AudioStreamBasicDescription in
,out
;
322 AudioBufferList outBuffer
;
323 AudioBuffer inBuffer
;
327 UInt32 NumberPackets
;
328 AudioStreamPacketDescription
*PacketDescriptions
;
331 /***********************************************************************
334 static LRESULT
MPEG3_drvOpen(LPCSTR str
)
339 /***********************************************************************
342 static LRESULT
MPEG3_drvClose(DWORD_PTR dwDevID
)
348 When it asks for data, give it all we have. If we have no data, we assume
349 we will in the future, so give it no packets and return an error, which
350 signals that we will have more later.
352 static OSStatus
Mp3AudioConverterComplexInputDataProc(
353 AudioConverterRef inAudioConverter
,
354 UInt32
*ioNumberDataPackets
,
355 AudioBufferList
*ioData
,
356 AudioStreamPacketDescription
**outDataPacketDescription
,
360 AcmMpeg3Data
*amd
= (AcmMpeg3Data
*)inUserData
;
362 if (amd
->inBuffer
.mDataByteSize
> 0)
364 *ioNumberDataPackets
= amd
->NumberPackets
;
365 ioData
->mNumberBuffers
= 1;
366 ioData
->mBuffers
[0] = amd
->inBuffer
;
367 amd
->inBuffer
.mDataByteSize
= 0;
368 if (outDataPacketDescription
)
369 *outDataPacketDescription
= amd
->PacketDescriptions
;
374 *ioNumberDataPackets
= 0;
380 Get the length of the current frame. We need to be at the start of a
381 frame now. The buffer must have at least the four bytes for the header.
383 static SInt32
Mp3GetPacketLength(const unsigned char* src
)
386 unsigned short brate
, srate
;
390 Check that our position looks like an MP3 header and see which type
393 if (src
[0] == 0xff && src
[1] >> 1 == 0x7d) mpegv
= 0; /* MPEG-1 File */
394 else if (src
[0] == 0xff && src
[1] >> 1 == 0x79) mpegv
= 1; /* MPEG-2 File */
397 /* Fill in bit rate and sample rate. */
398 brate
= Mp3BitRates
[mpegv
][(src
[2] & 0xf0) >> 4];
399 srate
= Mp3SampleRates
[mpegv
][(src
[2] & 0xc) >> 2];
401 /* Certain values for bit rate and sample rate are invalid. */
402 if (brate
== 0 || srate
== 0) return -1;
404 /* Compute frame size, round down */
405 size
= 72 * (2 - mpegv
) * brate
* 1000 / srate
;
407 /* If there is padding, add one byte */
408 if (src
[2] & 0x2) return size
+ 1;
413 Apple's AudioFileStream does weird things so we deal with parsing the
414 file ourselves. It was also designed for a different use case, so this
415 is not unexpected. We expect to have MP3 data as input (i.e. we can only
416 deal with MPEG-1 or MPEG-2 Layer III), which simplifies parsing a bit. We
417 understand the ID3v2 header and skip over it. Whenever we have data we
418 want to skip at the beginning of the input, we do this by setting *ndst=0
419 and *nsrc to the length of the unwanted data and return no error.
421 static LRESULT
mp3_leopard_horse(PACMDRVSTREAMINSTANCE adsi
,
422 unsigned char* src
, LPDWORD nsrc
,
423 unsigned char* dst
, LPDWORD ndst
)
426 UInt32 size
, aspdi
, synci
, syncSkip
;
428 const unsigned char* psrc
;
429 AcmMpeg3Data
* amd
= (AcmMpeg3Data
*)adsi
->dwDriver
;
431 TRACE("ndst %u %p <- %u %p\n", *ndst
, dst
, *nsrc
, src
);
433 TRACE("First 16 bytes to input: %s\n", wine_dbgstr_an((const char *)src
, 16));
436 if (!memcmp(src
, "ID3", 3) && amd
->tagBytesLeft
== -1)
438 amd
->tagBytesLeft
= (src
[6] << 21) + (src
[7] << 14) + (src
[8] << 7) + src
[9];
439 if (src
[5] & 0x10) amd
->tagBytesLeft
+= 20; /* There is a footer */
440 else amd
->tagBytesLeft
+= 10;
443 /* Consume the tag */
444 if (amd
->tagBytesLeft
>= (SInt32
)*nsrc
)
447 amd
->tagBytesLeft
-= *nsrc
;
449 TRACE("All %d bytes of source data is ID3 tag\n", *nsrc
);
450 return MMSYSERR_NOERROR
;
452 else if (amd
->tagBytesLeft
> 0)
454 src
+= amd
->tagBytesLeft
;
455 *nsrc
-= amd
->tagBytesLeft
;
456 TRACE("Skipping %ld for ID3 tag\n", amd
->tagBytesLeft
);
460 Sync to initial MP3 frame. The largest possible MP3 frame is 1440.
461 Thus, in the first 1440 bytes we must find the beginning of 3 valid
462 frames in a row unless we reach the end of the file first.
465 for (psrc
= src
; psrc
<= src
+ *nsrc
- 4 && psrc
< src
+ 1440; psrc
++)
469 synci
< 4 && psrc
+ framelen
[synci
-1] < src
+ *nsrc
- 4;
472 framelen
[synci
] = Mp3GetPacketLength(psrc
+ framelen
[synci
-1]);
473 if (framelen
[synci
] == -1)
478 framelen
[synci
] += framelen
[synci
-1];
480 if (synci
> 0) /* We synced successfully */
484 syncSkip
= psrc
- src
;
487 TRACE("Skipping %ld for frame sync\n", syncSkip
);
493 if (Mp3GetPacketLength(src
) == -1)
496 ERR("Frame sync failed. Cannot play file.\n");
497 return MMSYSERR_ERROR
;
501 Fill in frame descriptions for all frames. We use an extra pointer
502 to keep track of our position in the input.
505 amd
->NumberPackets
= 25; /* This is the initial array capacity */
506 amd
->PacketDescriptions
= HeapAlloc(GetProcessHeap(), 0, amd
->NumberPackets
* sizeof(AudioStreamPacketDescription
));
507 if (amd
->PacketDescriptions
== 0) return MMSYSERR_NOMEM
;
509 for (aspdi
= 0, psrc
= src
;
510 psrc
<= src
+ *nsrc
- 4;
511 psrc
+= amd
->PacketDescriptions
[aspdi
].mDataByteSize
, aspdi
++)
513 /* Return an error if we can't read the frame header */
514 if (Mp3GetPacketLength(psrc
) == -1)
517 ERR("Invalid header at %p.\n", psrc
);
518 HeapFree(GetProcessHeap(), 0, amd
->PacketDescriptions
);
519 return MMSYSERR_ERROR
;
522 /* If we run out of space, double size and reallocate */
523 if (aspdi
>= amd
->NumberPackets
)
525 amd
->NumberPackets
*= 2;
526 amd
->PacketDescriptions
= HeapReAlloc(GetProcessHeap(), 0, amd
->PacketDescriptions
, amd
->NumberPackets
* sizeof(AudioStreamPacketDescription
));
527 if (amd
->PacketDescriptions
== 0) return MMSYSERR_NOMEM
;
530 /* Fill in packet data */
531 amd
->PacketDescriptions
[aspdi
].mStartOffset
= psrc
- src
;
532 amd
->PacketDescriptions
[aspdi
].mVariableFramesInPacket
= 0;
533 amd
->PacketDescriptions
[aspdi
].mDataByteSize
= Mp3GetPacketLength(psrc
);
535 /* If this brings us past the end, the last one doesn't count */
536 if (psrc
+ amd
->PacketDescriptions
[aspdi
].mDataByteSize
> src
+ *nsrc
) break;
539 /* Fill in correct number of frames */
540 amd
->NumberPackets
= aspdi
;
542 /* Adjust nsrc to only include full frames */
545 amd
->inBuffer
.mDataByteSize
= *nsrc
;
546 amd
->inBuffer
.mData
= src
;
547 amd
->inBuffer
.mNumberChannels
= amd
->in
.mChannelsPerFrame
;
549 amd
->outBuffer
.mNumberBuffers
= 1;
550 amd
->outBuffer
.mBuffers
[0].mDataByteSize
= *ndst
;
551 amd
->outBuffer
.mBuffers
[0].mData
= dst
;
552 amd
->outBuffer
.mBuffers
[0].mNumberChannels
= amd
->out
.mChannelsPerFrame
;
554 /* Convert the data */
555 size
= amd
->outBuffer
.mBuffers
[0].mDataByteSize
/ amd
->out
.mBytesPerPacket
;
556 err
= AudioConverterFillComplexBuffer(amd
->acr
, Mp3AudioConverterComplexInputDataProc
, amd
, &size
, &amd
->outBuffer
, 0);
558 HeapFree(GetProcessHeap(), 0, amd
->PacketDescriptions
);
560 /* Add skipped bytes back into *nsrc */
561 if (amd
->tagBytesLeft
> 0)
563 *nsrc
+= amd
->tagBytesLeft
;
564 amd
->tagBytesLeft
= 0;
568 if (err
!= noErr
&& err
!= -74)
571 ERR("Feed Error: %ld\n", err
);
572 return MMSYSERR_ERROR
;
575 *ndst
= amd
->outBuffer
.mBuffers
[0].mDataByteSize
;
577 TRACE("convert %d -> %d\n", *nsrc
, *ndst
);
579 return MMSYSERR_NOERROR
;
582 /***********************************************************************
586 static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi
, AcmMpeg3Data
* aad
)
588 AudioConverterReset(aad
->acr
);
591 /***********************************************************************
595 static LRESULT
MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi
)
599 assert(!(adsi
->fdwOpen
& ACM_STREAMOPENF_ASYNC
));
601 if (MPEG3_GetFormatIndex(adsi
->pwfxSrc
) == 0xFFFFFFFF ||
602 MPEG3_GetFormatIndex(adsi
->pwfxDst
) == 0xFFFFFFFF)
603 return ACMERR_NOTPOSSIBLE
;
605 aad
= HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data
));
606 if (aad
== 0) return MMSYSERR_NOMEM
;
608 adsi
->dwDriver
= (DWORD_PTR
)aad
;
610 if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
||
611 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEG
) &&
612 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
616 aad
->in
.mSampleRate
= adsi
->pwfxSrc
->nSamplesPerSec
;
617 aad
->out
.mSampleRate
= adsi
->pwfxDst
->nSamplesPerSec
;
618 aad
->in
.mBitsPerChannel
= adsi
->pwfxSrc
->wBitsPerSample
;
619 aad
->out
.mBitsPerChannel
= adsi
->pwfxDst
->wBitsPerSample
;
620 aad
->in
.mFormatID
= kAudioFormatMPEGLayer3
;
621 aad
->out
.mFormatID
= kAudioFormatLinearPCM
;
622 aad
->in
.mChannelsPerFrame
= adsi
->pwfxSrc
->nChannels
;
623 aad
->out
.mChannelsPerFrame
= adsi
->pwfxDst
->nChannels
;
624 aad
->in
.mFormatFlags
= 0;
625 aad
->out
.mFormatFlags
= kLinearPCMFormatFlagIsSignedInteger
;
626 aad
->in
.mBytesPerFrame
= 0;
627 aad
->out
.mBytesPerFrame
= (aad
->out
.mBitsPerChannel
* aad
->out
.mChannelsPerFrame
) / 8;
628 aad
->in
.mBytesPerPacket
= 0;
629 aad
->out
.mBytesPerPacket
= aad
->out
.mBytesPerFrame
;
630 aad
->in
.mFramesPerPacket
= 0;
631 aad
->out
.mFramesPerPacket
= 1;
632 aad
->in
.mReserved
= aad
->out
.mReserved
= 0;
634 aad
->tagBytesLeft
= -1;
636 aad
->convert
= mp3_leopard_horse
;
638 err
= AudioConverterNew(&aad
->in
, &aad
->out
, &aad
->acr
);
641 ERR("Create failed: %ld\n", err
);
645 MPEG3_Reset(adsi
, aad
);
647 return MMSYSERR_NOERROR
;
651 HeapFree(GetProcessHeap(), 0, aad
);
654 return MMSYSERR_NOTSUPPORTED
;
657 /***********************************************************************
661 static LRESULT
MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi
)
663 AcmMpeg3Data
* amd
= (AcmMpeg3Data
*)adsi
->dwDriver
;
665 AudioConverterDispose(amd
->acr
);
667 HeapFree(GetProcessHeap(), 0, amd
);
670 return MMSYSERR_NOERROR
;
675 /***********************************************************************
676 * MPEG3_DriverDetails
679 static LRESULT
MPEG3_DriverDetails(PACMDRIVERDETAILSW add
)
681 add
->fccType
= ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC
;
682 add
->fccComp
= ACMDRIVERDETAILS_FCCCOMP_UNDEFINED
;
683 add
->wMid
= MM_FRAUNHOFER_IIS
;
684 add
->wPid
= MM_FHGIIS_MPEGLAYER3_DECODE
;
685 add
->vdwACM
= 0x01000000;
686 add
->vdwDriver
= 0x01000000;
687 add
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
688 add
->cFormatTags
= 3; /* PCM, MPEG3 */
689 add
->cFilterTags
= 0;
691 MultiByteToWideChar( CP_ACP
, 0, "MPEG Layer-3 Codec", -1,
692 add
->szShortName
, sizeof(add
->szShortName
)/sizeof(WCHAR
) );
693 MultiByteToWideChar( CP_ACP
, 0, "Wine MPEG3 decoder", -1,
694 add
->szLongName
, sizeof(add
->szLongName
)/sizeof(WCHAR
) );
695 MultiByteToWideChar( CP_ACP
, 0, "Brought to you by the Wine team...", -1,
696 add
->szCopyright
, sizeof(add
->szCopyright
)/sizeof(WCHAR
) );
697 MultiByteToWideChar( CP_ACP
, 0, "Refer to LICENSE file", -1,
698 add
->szLicensing
, sizeof(add
->szLicensing
)/sizeof(WCHAR
) );
699 add
->szFeatures
[0] = 0;
701 return MMSYSERR_NOERROR
;
704 /***********************************************************************
705 * MPEG3_FormatTagDetails
708 static LRESULT
MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd
, DWORD dwQuery
)
710 static const WCHAR szPcm
[]={'P','C','M',0};
711 static const WCHAR szMpeg3
[]={'M','P','e','g','3',0};
712 static const WCHAR szMpeg
[]={'M','P','e','g',0};
716 case ACM_FORMATTAGDETAILSF_INDEX
:
717 if (aftd
->dwFormatTagIndex
> 2) return ACMERR_NOTPOSSIBLE
;
719 case ACM_FORMATTAGDETAILSF_LARGESTSIZE
:
720 if (aftd
->dwFormatTag
== WAVE_FORMAT_UNKNOWN
)
722 aftd
->dwFormatTagIndex
= 2; /* WAVE_FORMAT_MPEG is biggest */
726 case ACM_FORMATTAGDETAILSF_FORMATTAG
:
727 switch (aftd
->dwFormatTag
)
729 case WAVE_FORMAT_PCM
: aftd
->dwFormatTagIndex
= 0; break;
730 case WAVE_FORMAT_MPEGLAYER3
: aftd
->dwFormatTagIndex
= 1; break;
731 case WAVE_FORMAT_MPEG
: aftd
->dwFormatTagIndex
= 2; break;
732 default: return ACMERR_NOTPOSSIBLE
;
736 WARN("Unsupported query %08x\n", dwQuery
);
737 return MMSYSERR_NOTSUPPORTED
;
740 aftd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
741 switch (aftd
->dwFormatTagIndex
)
744 aftd
->dwFormatTag
= WAVE_FORMAT_PCM
;
745 aftd
->cbFormatSize
= sizeof(PCMWAVEFORMAT
);
746 aftd
->cStandardFormats
= NUM_PCM_FORMATS
;
747 lstrcpyW(aftd
->szFormatTag
, szPcm
);
750 aftd
->dwFormatTag
= WAVE_FORMAT_MPEGLAYER3
;
751 aftd
->cbFormatSize
= sizeof(MPEGLAYER3WAVEFORMAT
);
752 aftd
->cStandardFormats
= NUM_MPEG3_FORMATS
;
753 lstrcpyW(aftd
->szFormatTag
, szMpeg3
);
756 aftd
->dwFormatTag
= WAVE_FORMAT_MPEG
;
757 aftd
->cbFormatSize
= sizeof(MPEG1WAVEFORMAT
);
758 aftd
->cStandardFormats
= NUM_MPEG3_FORMATS
;
759 lstrcpyW(aftd
->szFormatTag
, szMpeg
);
762 return MMSYSERR_NOERROR
;
765 static void fill_in_mp3(unsigned cbwfx
, WAVEFORMATEX
* wfx
, unsigned bit_rate
)
767 MPEGLAYER3WAVEFORMAT
* mp3wfx
= (MPEGLAYER3WAVEFORMAT
*)wfx
;
769 wfx
->nAvgBytesPerSec
= bit_rate
/ 8;
770 if (cbwfx
>= sizeof(WAVEFORMATEX
))
771 wfx
->cbSize
= sizeof(MPEGLAYER3WAVEFORMAT
) - sizeof(WAVEFORMATEX
);
772 if (cbwfx
>= sizeof(MPEGLAYER3WAVEFORMAT
))
774 mp3wfx
->wID
= MPEGLAYER3_ID_MPEG
;
775 mp3wfx
->fdwFlags
= MPEGLAYER3_FLAG_PADDING_OFF
;
776 mp3wfx
->nBlockSize
= (bit_rate
* 144) / wfx
->nSamplesPerSec
;
777 mp3wfx
->nFramesPerBlock
= 1;
778 mp3wfx
->nCodecDelay
= 0x0571;
782 static void fill_in_mpeg(unsigned cbwfx
, WAVEFORMATEX
* wfx
, unsigned bit_rate
)
784 MPEG1WAVEFORMAT
* mp3wfx
= (MPEG1WAVEFORMAT
*)wfx
;
786 wfx
->nAvgBytesPerSec
= bit_rate
/ 8;
787 if (cbwfx
>= sizeof(WAVEFORMATEX
))
788 wfx
->cbSize
= sizeof(MPEG1WAVEFORMAT
) - sizeof(WAVEFORMATEX
);
789 if (cbwfx
>= sizeof(MPEG1WAVEFORMAT
))
791 mp3wfx
->fwHeadLayer
= ACM_MPEG_LAYER3
;
792 mp3wfx
->dwHeadBitrate
= wfx
->nAvgBytesPerSec
* 8;
793 mp3wfx
->fwHeadMode
= ACM_MPEG_JOINTSTEREO
;
794 mp3wfx
->fwHeadModeExt
= 0xf;
795 mp3wfx
->wHeadEmphasis
= 1;
796 mp3wfx
->fwHeadFlags
= ACM_MPEG_ID_MPEG1
;
800 /***********************************************************************
801 * MPEG3_FormatDetails
804 static LRESULT
MPEG3_FormatDetails(PACMFORMATDETAILSW afd
, DWORD dwQuery
)
808 case ACM_FORMATDETAILSF_FORMAT
:
809 if (MPEG3_GetFormatIndex(afd
->pwfx
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
811 case ACM_FORMATDETAILSF_INDEX
:
812 afd
->pwfx
->wFormatTag
= afd
->dwFormatTag
;
813 switch (afd
->dwFormatTag
)
815 case WAVE_FORMAT_PCM
:
816 if (afd
->dwFormatIndex
>= NUM_PCM_FORMATS
) return ACMERR_NOTPOSSIBLE
;
817 afd
->pwfx
->nChannels
= PCM_Formats
[afd
->dwFormatIndex
].nChannels
;
818 afd
->pwfx
->nSamplesPerSec
= PCM_Formats
[afd
->dwFormatIndex
].rate
;
819 afd
->pwfx
->wBitsPerSample
= PCM_Formats
[afd
->dwFormatIndex
].nBits
;
820 /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
821 * afd->pwfx->cbSize = 0;
823 afd
->pwfx
->nBlockAlign
=
824 (afd
->pwfx
->nChannels
* afd
->pwfx
->wBitsPerSample
) / 8;
825 afd
->pwfx
->nAvgBytesPerSec
=
826 afd
->pwfx
->nSamplesPerSec
* afd
->pwfx
->nBlockAlign
;
828 case WAVE_FORMAT_MPEGLAYER3
:
829 case WAVE_FORMAT_MPEG
:
830 if (afd
->dwFormatIndex
>= NUM_MPEG3_FORMATS
) return ACMERR_NOTPOSSIBLE
;
831 afd
->pwfx
->nChannels
= MPEG3_Formats
[afd
->dwFormatIndex
].nChannels
;
832 afd
->pwfx
->nSamplesPerSec
= MPEG3_Formats
[afd
->dwFormatIndex
].rate
;
833 afd
->pwfx
->wBitsPerSample
= MPEG3_Formats
[afd
->dwFormatIndex
].nBits
;
834 afd
->pwfx
->nBlockAlign
= 1;
835 if (afd
->dwFormatTag
== WAVE_FORMAT_MPEGLAYER3
)
836 fill_in_mp3(afd
->cbwfx
, afd
->pwfx
, 192000);
838 fill_in_mpeg(afd
->cbwfx
, afd
->pwfx
, 192000);
841 WARN("Unsupported tag %08x\n", afd
->dwFormatTag
);
842 return MMSYSERR_INVALPARAM
;
846 WARN("Unsupported query %08x\n", dwQuery
);
847 return MMSYSERR_NOTSUPPORTED
;
849 afd
->fdwSupport
= ACMDRIVERDETAILS_SUPPORTF_CODEC
;
850 afd
->szFormat
[0] = 0; /* let MSACM format this for us... */
852 return MMSYSERR_NOERROR
;
855 /***********************************************************************
856 * MPEG3_FormatSuggest
859 static LRESULT
MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs
)
862 if (adfs
->cbwfxSrc
< sizeof(PCMWAVEFORMAT
) ||
863 adfs
->cbwfxDst
< sizeof(PCMWAVEFORMAT
) ||
864 MPEG3_GetFormatIndex(adfs
->pwfxSrc
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
865 /* FIXME: should do those tests against the real size (according to format tag */
867 /* If no suggestion for destination, then copy source value */
868 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_NCHANNELS
))
869 adfs
->pwfxDst
->nChannels
= adfs
->pwfxSrc
->nChannels
;
870 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_NSAMPLESPERSEC
))
871 adfs
->pwfxDst
->nSamplesPerSec
= adfs
->pwfxSrc
->nSamplesPerSec
;
873 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WBITSPERSAMPLE
))
875 if (adfs
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
)
876 adfs
->pwfxDst
->wBitsPerSample
= 4;
878 adfs
->pwfxDst
->wBitsPerSample
= 16;
880 if (!(adfs
->fdwSuggest
& ACM_FORMATSUGGESTF_WFORMATTAG
))
882 if (adfs
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
)
883 adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_MPEGLAYER3
;
885 adfs
->pwfxDst
->wFormatTag
= WAVE_FORMAT_PCM
;
888 /* check if result is ok */
889 if (MPEG3_GetFormatIndex(adfs
->pwfxDst
) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE
;
891 /* recompute other values */
892 switch (adfs
->pwfxDst
->wFormatTag
)
894 case WAVE_FORMAT_PCM
:
895 adfs
->pwfxDst
->nBlockAlign
= (adfs
->pwfxDst
->nChannels
* adfs
->pwfxDst
->wBitsPerSample
) / 8;
896 adfs
->pwfxDst
->nAvgBytesPerSec
= adfs
->pwfxDst
->nSamplesPerSec
* adfs
->pwfxDst
->nBlockAlign
;
898 case WAVE_FORMAT_MPEG
:
899 adfs
->pwfxDst
->nBlockAlign
= 1;
900 fill_in_mpeg(adfs
->cbwfxDst
, adfs
->pwfxDst
, 192000);
902 case WAVE_FORMAT_MPEGLAYER3
:
903 adfs
->pwfxDst
->nBlockAlign
= 1;
904 fill_in_mp3(adfs
->cbwfxDst
, adfs
->pwfxDst
, 192000);
911 return MMSYSERR_NOERROR
;
914 /***********************************************************************
918 static LRESULT
MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMSIZE adss
)
922 switch (adss
->fdwSize
)
924 case ACM_STREAMSIZEF_DESTINATION
:
925 /* cbDstLength => cbSrcLength */
926 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
927 (adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
||
928 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MPEG
))
930 nblocks
= (adss
->cbDstLength
- 3000) / (DWORD
)(adsi
->pwfxDst
->nAvgBytesPerSec
* 1152 / adsi
->pwfxDst
->nSamplesPerSec
+ 0.5);
932 return ACMERR_NOTPOSSIBLE
;
933 adss
->cbSrcLength
= nblocks
* 1152 * adsi
->pwfxSrc
->nBlockAlign
;
935 else if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
||
936 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEG
) &&
937 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
939 nblocks
= adss
->cbDstLength
/ (adsi
->pwfxDst
->nBlockAlign
* 1152);
941 return ACMERR_NOTPOSSIBLE
;
942 adss
->cbSrcLength
= nblocks
* (DWORD
)(adsi
->pwfxSrc
->nAvgBytesPerSec
* 1152 / adsi
->pwfxSrc
->nSamplesPerSec
);
946 return MMSYSERR_NOTSUPPORTED
;
949 case ACM_STREAMSIZEF_SOURCE
:
950 /* cbSrcLength => cbDstLength */
951 if (adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_PCM
&&
952 (adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
||
953 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_MPEG
))
955 nblocks
= adss
->cbSrcLength
/ (adsi
->pwfxSrc
->nBlockAlign
* 1152);
956 if (adss
->cbSrcLength
% (DWORD
)(adsi
->pwfxSrc
->nBlockAlign
* 1152))
957 /* Round block count up. */
960 return ACMERR_NOTPOSSIBLE
;
961 adss
->cbDstLength
= 3000 + nblocks
* (DWORD
)(adsi
->pwfxDst
->nAvgBytesPerSec
* 1152 / adsi
->pwfxDst
->nSamplesPerSec
+ 0.5);
963 else if ((adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEGLAYER3
||
964 adsi
->pwfxSrc
->wFormatTag
== WAVE_FORMAT_MPEG
) &&
965 adsi
->pwfxDst
->wFormatTag
== WAVE_FORMAT_PCM
)
967 nblocks
= adss
->cbSrcLength
/ (DWORD
)(adsi
->pwfxSrc
->nAvgBytesPerSec
* 1152 / adsi
->pwfxSrc
->nSamplesPerSec
);
968 if (adss
->cbSrcLength
% (DWORD
)(adsi
->pwfxSrc
->nAvgBytesPerSec
* 1152 / adsi
->pwfxSrc
->nSamplesPerSec
))
969 /* Round block count up. */
972 return ACMERR_NOTPOSSIBLE
;
973 adss
->cbDstLength
= nblocks
* 1152 * adsi
->pwfxDst
->nBlockAlign
;
977 return MMSYSERR_NOTSUPPORTED
;
981 WARN("Unsupported query %08x\n", adss
->fdwSize
);
982 return MMSYSERR_NOTSUPPORTED
;
984 return MMSYSERR_NOERROR
;
987 /***********************************************************************
988 * MPEG3_StreamConvert
991 static LRESULT
MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi
, PACMDRVSTREAMHEADER adsh
)
993 AcmMpeg3Data
* aad
= (AcmMpeg3Data
*)adsi
->dwDriver
;
994 DWORD nsrc
= adsh
->cbSrcLength
;
995 DWORD ndst
= adsh
->cbDstLength
;
997 if (adsh
->fdwConvert
&
998 ~(ACM_STREAMCONVERTF_BLOCKALIGN
|
999 ACM_STREAMCONVERTF_END
|
1000 ACM_STREAMCONVERTF_START
))
1002 FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh
->fdwConvert
);
1004 /* ACM_STREAMCONVERTF_BLOCKALIGN
1005 * currently all conversions are block aligned, so do nothing for this flag
1006 * ACM_STREAMCONVERTF_END
1007 * no pending data, so do nothing for this flag
1009 if ((adsh
->fdwConvert
& ACM_STREAMCONVERTF_START
))
1011 MPEG3_Reset(adsi
, aad
);
1014 aad
->convert(adsi
, adsh
->pbSrc
, &nsrc
, adsh
->pbDst
, &ndst
);
1015 adsh
->cbSrcLengthUsed
= nsrc
;
1016 adsh
->cbDstLengthUsed
= ndst
;
1018 return MMSYSERR_NOERROR
;
1021 /**************************************************************************
1022 * MPEG3_DriverProc [exported]
1024 LRESULT CALLBACK
MPEG3_DriverProc(DWORD_PTR dwDevID
, HDRVR hDriv
, UINT wMsg
,
1025 LPARAM dwParam1
, LPARAM dwParam2
)
1027 TRACE("(%08lx %p %04x %08lx %08lx);\n",
1028 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1032 case DRV_LOAD
: return 1;
1033 case DRV_FREE
: return 1;
1034 case DRV_OPEN
: return MPEG3_drvOpen((LPSTR
)dwParam1
);
1035 case DRV_CLOSE
: return MPEG3_drvClose(dwDevID
);
1036 case DRV_ENABLE
: return 1;
1037 case DRV_DISABLE
: return 1;
1038 case DRV_QUERYCONFIGURE
: return 1;
1039 case DRV_CONFIGURE
: MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK
); return 1;
1040 case DRV_INSTALL
: return DRVCNF_RESTART
;
1041 case DRV_REMOVE
: return DRVCNF_RESTART
;
1043 case ACMDM_DRIVER_NOTIFY
:
1044 /* no caching from other ACM drivers is done so far */
1045 return MMSYSERR_NOERROR
;
1047 case ACMDM_DRIVER_DETAILS
:
1048 return MPEG3_DriverDetails((PACMDRIVERDETAILSW
)dwParam1
);
1050 case ACMDM_FORMATTAG_DETAILS
:
1051 return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW
)dwParam1
, dwParam2
);
1053 case ACMDM_FORMAT_DETAILS
:
1054 return MPEG3_FormatDetails((PACMFORMATDETAILSW
)dwParam1
, dwParam2
);
1056 case ACMDM_FORMAT_SUGGEST
:
1057 return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST
)dwParam1
);
1059 case ACMDM_STREAM_OPEN
:
1060 return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE
)dwParam1
);
1062 case ACMDM_STREAM_CLOSE
:
1063 return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE
)dwParam1
);
1065 case ACMDM_STREAM_SIZE
:
1066 return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMSIZE
)dwParam2
);
1068 case ACMDM_STREAM_CONVERT
:
1069 return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE
)dwParam1
, (PACMDRVSTREAMHEADER
)dwParam2
);
1071 case ACMDM_HARDWARE_WAVE_CAPS_INPUT
:
1072 case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT
:
1073 /* this converter is not a hardware driver */
1074 case ACMDM_FILTERTAG_DETAILS
:
1075 case ACMDM_FILTER_DETAILS
:
1076 /* this converter is not a filter */
1077 case ACMDM_STREAM_RESET
:
1078 /* only needed for asynchronous driver... we aren't, so just say it */
1079 return MMSYSERR_NOTSUPPORTED
;
1080 case ACMDM_STREAM_PREPARE
:
1081 case ACMDM_STREAM_UNPREPARE
:
1082 /* nothing special to do here... so don't do anything */
1083 return MMSYSERR_NOERROR
;
1086 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);