mpegl3.c 32.1 KB
Newer Older
1 2 3
/*
 * MPEG Layer 3 handling
 *
4 5
 * Copyright (C) 2002 Eric Pouech
 * Copyright (C) 2009 CodeWeavers, Aric Stewart
6
 * Copyright (C) 2010 Kristofer Henriksson
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 23
 */

24
#include "config.h"
25
#include "wine/port.h"
26

27
#include <assert.h>
28
#include <stdarg.h>
29
#include <string.h>
30 31 32 33 34 35 36 37 38 39 40 41 42

#ifdef HAVE_MPG123_H
# include <mpg123.h>
#else
# ifdef HAVE_COREAUDIO_COREAUDIO_H
#  include <CoreFoundation/CoreFoundation.h>
#  include <CoreAudio/CoreAudio.h>
# endif
# ifdef HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H
#  include <AudioToolbox/AudioConverter.h>
# endif
#endif

43
#include "windef.h"
44 45 46
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
47
#include "winnls.h"
48
#include "mmsystem.h"
49
#include "mmreg.h"
50
#include "msacm.h"
51
#include "msacmdrv.h"
52 53 54 55 56 57 58
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(mpeg3);

/* table to list all supported formats... those are the basic ones. this
 * also helps given a unique index to each of the supported formats
 */
59
typedef	struct
60 61 62 63 64 65
{
    int		nChannels;
    int		nBits;
    int		rate;
} Format;

66
static const Format PCM_Formats[] =
67 68 69
{
    {1,  8,  8000}, {2,  8,  8000}, {1, 16,  8000}, {2, 16,  8000},
    {1,  8, 11025}, {2,  8, 11025}, {1, 16, 11025}, {2, 16, 11025},
70 71
    {1,  8, 12000}, {2,  8, 12000}, {1, 16, 12000}, {2, 16, 12000},
    {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 74
    {1,  8, 24000}, {2,  8, 24000}, {1, 16, 24000}, {2, 16, 24000},
    {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}
77 78
};

79
static const Format MPEG3_Formats[] =
80
{
81 82 83 84 85 86 87 88 89
    {1,  0,  8000}, {2,  0,  8000},
    {1,  0, 11025}, {2,  0, 11025},
    {1,  0, 12000}, {2,  0, 12000},
    {1,  0, 16000}, {2,  0, 16000},
    {1,  0, 22050}, {2,  0, 22050},
    {1,  0, 24000}, {2,  0, 24000},
    {1,  0, 32000}, {2,  0, 32000},
    {1,  0, 44100}, {2,  0, 44100},
    {1,  0, 48000}, {2,  0, 48000}
90 91 92 93 94 95 96 97
};

/***********************************************************************
 *           MPEG3_GetFormatIndex
 */
static	DWORD	MPEG3_GetFormatIndex(LPWAVEFORMATEX wfx)
{
    int 	i, hi;
98
    const Format *fmts;
99 100

    switch (wfx->wFormatTag)
101 102
    {
    case WAVE_FORMAT_PCM:
103
	hi = ARRAY_SIZE(PCM_Formats);
104 105
	fmts = PCM_Formats;
	break;
106
    case WAVE_FORMAT_MPEG:
107
    case WAVE_FORMAT_MPEGLAYER3:
108
	hi = ARRAY_SIZE(MPEG3_Formats);
109 110 111 112 113
	fmts = MPEG3_Formats;
	break;
    default:
	return 0xFFFFFFFF;
    }
114 115

    for (i = 0; i < hi; i++)
116 117 118
    {
	if (wfx->nChannels == fmts[i].nChannels &&
	    wfx->nSamplesPerSec == fmts[i].rate &&
119
	    (wfx->wBitsPerSample == fmts[i].nBits || !fmts[i].nBits))
120 121
	    return i;
    }
122

123 124 125
    return 0xFFFFFFFF;
}

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
#ifdef HAVE_MPG123_H

typedef struct tagAcmMpeg3Data
{
    void (*convert)(PACMDRVSTREAMINSTANCE adsi,
		    const unsigned char*, LPDWORD, unsigned char*, LPDWORD);
    mpg123_handle *mh;
} AcmMpeg3Data;

/***********************************************************************
 *           MPEG3_drvOpen
 */
static LRESULT MPEG3_drvOpen(LPCSTR str)
{
    mpg123_init();
    return 1;
}

/***********************************************************************
 *           MPEG3_drvClose
 */
static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
{
    mpg123_exit();
    return 1;
}


154 155 156 157 158
static void mp3_horse(PACMDRVSTREAMINSTANCE adsi,
                      const unsigned char* src, LPDWORD nsrc,
                      unsigned char* dst, LPDWORD ndst)
{
    AcmMpeg3Data*       amd = (AcmMpeg3Data*)adsi->dwDriver;
159 160
    int                 ret;
    size_t              size;
161 162
    DWORD               dpos = 0;

163

164
    if (*nsrc > 0)
165
    {
166 167
        ret = mpg123_feed(amd->mh, src, *nsrc);
        if (ret != MPG123_OK)
168
        {
169 170 171
            ERR("Error feeding data\n");
            *ndst = *nsrc = 0;
            return;
172 173 174
        }
    }

175
    do {
176
        size = 0;
177
        ret = mpg123_read(amd->mh, dst + dpos, *ndst - dpos, &size);
178 179 180 181 182 183 184 185 186
        if (ret == MPG123_ERR)
        {
            FIXME("Error occurred during decoding!\n");
            *ndst = *nsrc = 0;
            return;
        }

        if (ret == MPG123_NEW_FORMAT)
        {
187 188 189 190
            long rate;
            int channels, enc;
            mpg123_getformat(amd->mh, &rate, &channels, &enc);
            TRACE("New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
191 192
        }
        dpos += size;
193
        if (dpos >= *ndst) break;
194
    } while (ret != MPG123_ERR && ret != MPG123_NEED_MORE);
195 196 197
    *ndst = dpos;
}

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
/***********************************************************************
 *           MPEG3_Reset
 *
 */
static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
{
    mpg123_feedseek(aad->mh, 0, SEEK_SET, NULL);
    mpg123_close(aad->mh);
    mpg123_open_feed(aad->mh);
}

/***********************************************************************
 *           MPEG3_StreamOpen
 *
 */
static	LRESULT	MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
{
    AcmMpeg3Data*	aad;
    int err;

    assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));

    if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
	MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
	return ACMERR_NOTPOSSIBLE;

    aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
    if (aad == 0) return MMSYSERR_NOMEM;

    adsi->dwDriver = (DWORD_PTR)aad;

    if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
	adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
    {
	goto theEnd;
    }
234 235
    else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
              adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
236 237 238 239 240 241 242 243 244 245 246 247
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
    {
	/* resampling or mono <=> stereo not available
         * MPEG3 algo only define 16 bit per sample output
         */
	if (adsi->pwfxSrc->nSamplesPerSec != adsi->pwfxDst->nSamplesPerSec ||
	    adsi->pwfxSrc->nChannels != adsi->pwfxDst->nChannels ||
            adsi->pwfxDst->wBitsPerSample != 16)
	    goto theEnd;
        aad->convert = mp3_horse;
        aad->mh = mpg123_new(NULL,&err);
        mpg123_open_feed(aad->mh);
248

249
#if MPG123_API_VERSION >= 31 /* needed for MPG123_IGNORE_FRAMEINFO enum value */
250 251 252 253 254 255
        /* mpg123 may find a XING header in the mp3 and use that information
         * to ask for seeks in order to read specific frames in the file.
         * We cannot allow that since the caller application is feeding us.
         * This fixes problems for mp3 files encoded with LAME (bug 42361)
         */
        mpg123_param(aad->mh, MPG123_ADD_FLAGS, MPG123_IGNORE_INFOFRAME, 0);
256
#endif
257 258
    }
    else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
259 260 261 262 263 264
             (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
              adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
    {
        WARN("Encoding to MPEG is not supported\n");
        goto theEnd;
    }
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
    else goto theEnd;
    MPEG3_Reset(adsi, aad);

    return MMSYSERR_NOERROR;

 theEnd:
    HeapFree(GetProcessHeap(), 0, aad);
    adsi->dwDriver = 0L;
    return MMSYSERR_NOTSUPPORTED;
}

/***********************************************************************
 *           MPEG3_StreamClose
 *
 */
static	LRESULT	MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
{
    mpg123_close(((AcmMpeg3Data*)adsi->dwDriver)->mh);
    mpg123_delete(((AcmMpeg3Data*)adsi->dwDriver)->mh);
    HeapFree(GetProcessHeap(), 0, (void*)adsi->dwDriver);
    return MMSYSERR_NOERROR;
}

288 289 290 291 292 293 294 295 296 297 298 299 300
#elif defined(HAVE_AUDIOTOOLBOX_AUDIOCONVERTER_H)

static const unsigned short Mp3BitRates[2][16] =
{
    {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0},
    {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}
};

static const unsigned short Mp3SampleRates[2][4] =
{
    {44100, 48000, 32000, 0},
    {22050, 24000, 16000, 0}
};
301 302 303

typedef struct tagAcmMpeg3Data
{
304
    LRESULT (*convert)(PACMDRVSTREAMINSTANCE adsi, unsigned char*,
305
                       LPDWORD, unsigned char*, LPDWORD);
306 307 308 309 310 311
    AudioConverterRef acr;
    AudioStreamBasicDescription in,out;

    AudioBufferList outBuffer;
    AudioBuffer inBuffer;

312 313
    SInt32 tagBytesLeft;

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
    UInt32 NumberPackets;
    AudioStreamPacketDescription *PacketDescriptions;
} AcmMpeg3Data;

/***********************************************************************
 *           MPEG3_drvOpen
 */
static LRESULT MPEG3_drvOpen(LPCSTR str)
{
    return 1;
}

/***********************************************************************
 *           MPEG3_drvClose
 */
static LRESULT MPEG3_drvClose(DWORD_PTR dwDevID)
{
    return 1;
}

334 335 336 337 338 339
/*
 When it asks for data, give it all we have. If we have no data, we assume
 we will in the future, so give it no packets and return an error, which
 signals that we will have more later.
 */
static OSStatus Mp3AudioConverterComplexInputDataProc(
340 341 342 343 344 345 346 347 348 349 350 351 352
   AudioConverterRef             inAudioConverter,
   UInt32                        *ioNumberDataPackets,
   AudioBufferList               *ioData,
   AudioStreamPacketDescription  **outDataPacketDescription,
   void                          *inUserData
)
{
    AcmMpeg3Data *amd = (AcmMpeg3Data*)inUserData;

    if (amd->inBuffer.mDataByteSize > 0)
    {
        *ioNumberDataPackets = amd->NumberPackets;
        ioData->mNumberBuffers = 1;
353
        ioData->mBuffers[0] = amd->inBuffer;
354 355 356
        amd->inBuffer.mDataByteSize = 0;
        if (outDataPacketDescription)
            *outDataPacketDescription = amd->PacketDescriptions;
357
        return noErr;
358 359
    }
    else
360
    {
361
        *ioNumberDataPackets = 0;
362 363
        return -74;
    }
364 365
}

366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
/*
 Get the length of the current frame. We need to be at the start of a
 frame now. The buffer must have at least the four bytes for the header.
 */
static SInt32 Mp3GetPacketLength(const unsigned char* src)
{
    unsigned char mpegv;
    unsigned short brate, srate;
    unsigned int size;

    /*
     Check that our position looks like an MP3 header and see which type
     of MP3 file we have.
     */
    if (src[0] == 0xff && src[1] >> 1 == 0x7d) mpegv = 0; /* MPEG-1 File */
    else if (src[0] == 0xff && src[1] >> 1 == 0x79) mpegv = 1; /* MPEG-2 File */
    else return -1;

    /* Fill in bit rate and sample rate. */
    brate = Mp3BitRates[mpegv][(src[2] & 0xf0) >> 4];
    srate = Mp3SampleRates[mpegv][(src[2] & 0xc) >> 2];

    /* Certain values for bit rate and sample rate are invalid. */
    if (brate == 0 || srate == 0) return -1;

    /* Compute frame size, round down */
    size = 72 * (2 - mpegv) * brate * 1000 / srate;

    /* If there is padding, add one byte */
    if (src[2] & 0x2) return size + 1;
    else return size;
}

/*
 Apple's AudioFileStream does weird things so we deal with parsing the
 file ourselves. It was also designed for a different use case, so this
 is not unexpected. We expect to have MP3 data as input (i.e. we can only
 deal with MPEG-1 or MPEG-2 Layer III), which simplifies parsing a bit. We
 understand the ID3v2 header and skip over it. Whenever we have data we
 want to skip at the beginning of the input, we do this by setting *ndst=0
 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)
411
{
412 413 414 415 416 417 418 419
    OSStatus err;
    UInt32 size, aspdi, synci, syncSkip;
    short framelen[4];
    const unsigned char* psrc;
    AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;

    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));
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442

    /* Parse ID3 tag */
    if (!memcmp(src, "ID3", 3) && amd->tagBytesLeft == -1)
    {
        amd->tagBytesLeft = (src[6] << 21) + (src[7] << 14) + (src[8] << 7) + src[9];
        if (src[5] & 0x10) amd->tagBytesLeft += 20; /* There is a footer */
        else amd->tagBytesLeft += 10;
    }

    /* Consume the tag */
    if (amd->tagBytesLeft >= (SInt32)*nsrc)
    {
        *ndst = 0;
        amd->tagBytesLeft -= *nsrc;

        TRACE("All %d bytes of source data is ID3 tag\n", *nsrc);
        return MMSYSERR_NOERROR;
    }
    else if (amd->tagBytesLeft > 0)
    {
        src += amd->tagBytesLeft;
        *nsrc -= amd->tagBytesLeft;
443
        TRACE("Skipping %ld for ID3 tag\n", amd->tagBytesLeft);
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
    }

    /*
     Sync to initial MP3 frame. The largest possible MP3 frame is 1440.
     Thus, in the first 1440 bytes we must find the beginning of 3 valid
     frames in a row unless we reach the end of the file first.
     */
    syncSkip = 0;
    for (psrc = src; psrc <= src + *nsrc - 4 && psrc < src + 1440; psrc++)
    {
        framelen[0] = 0;
        for (synci = 1;
             synci < 4 && psrc + framelen[synci-1] < src + *nsrc - 4;
             synci++)
        {
            framelen[synci] = Mp3GetPacketLength(psrc + framelen[synci-1]);
            if (framelen[synci] == -1)
            {
                synci = 0;
                break;
            }
            framelen[synci] += framelen[synci-1];
        }
        if (synci > 0) /* We synced successfully */
        {
            if (psrc - src > 0)
            {
                syncSkip = psrc - src;
                src += syncSkip;
                *nsrc -= syncSkip;
474
                TRACE("Skipping %ld for frame sync\n", syncSkip);
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
            }
            break;
        }
    }

    if (Mp3GetPacketLength(src) == -1)
    {
        *ndst = *nsrc = 0;
        ERR("Frame sync failed. Cannot play file.\n");
        return MMSYSERR_ERROR;
    }

    /*
     Fill in frame descriptions for all frames. We use an extra pointer
     to keep track of our position in the input.
     */

    amd->NumberPackets = 25; /* This is the initial array capacity */
    amd->PacketDescriptions = HeapAlloc(GetProcessHeap(), 0, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
    if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;

    for (aspdi = 0, psrc = src;
         psrc <= src + *nsrc - 4;
         psrc += amd->PacketDescriptions[aspdi].mDataByteSize, aspdi++)
    {
        /* Return an error if we can't read the frame header */
        if (Mp3GetPacketLength(psrc) == -1)
        {
            *ndst = *nsrc = 0;
            ERR("Invalid header at %p.\n", psrc);
            HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);
            return MMSYSERR_ERROR;
        }

        /* If we run out of space, double size and reallocate */
        if (aspdi >= amd->NumberPackets)
        {
            amd->NumberPackets *= 2;
            amd->PacketDescriptions = HeapReAlloc(GetProcessHeap(), 0, amd->PacketDescriptions, amd->NumberPackets * sizeof(AudioStreamPacketDescription));
            if (amd->PacketDescriptions == 0) return MMSYSERR_NOMEM;
        }

        /* Fill in packet data */
        amd->PacketDescriptions[aspdi].mStartOffset = psrc - src;
        amd->PacketDescriptions[aspdi].mVariableFramesInPacket = 0;
        amd->PacketDescriptions[aspdi].mDataByteSize = Mp3GetPacketLength(psrc);

        /* If this brings us past the end, the last one doesn't count */
        if (psrc + amd->PacketDescriptions[aspdi].mDataByteSize > src + *nsrc) break;
    }

    /* Fill in correct number of frames */
    amd->NumberPackets = aspdi;

    /* Adjust nsrc to only include full frames */
    *nsrc = psrc - src;

    amd->inBuffer.mDataByteSize = *nsrc;
    amd->inBuffer.mData = src;
    amd->inBuffer.mNumberChannels = amd->in.mChannelsPerFrame;
535 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;
540

541 542 543
    /* Convert the data */
    size = amd->outBuffer.mBuffers[0].mDataByteSize / amd->out.mBytesPerPacket;
    err = AudioConverterFillComplexBuffer(amd->acr, Mp3AudioConverterComplexInputDataProc, amd, &size, &amd->outBuffer, 0);
544

545 546 547 548
    HeapFree(GetProcessHeap(), 0, amd->PacketDescriptions);

    /* Add skipped bytes back into *nsrc */
    if (amd->tagBytesLeft > 0)
549
    {
550 551
        *nsrc += amd->tagBytesLeft;
        amd->tagBytesLeft = 0;
552
    }
553 554 555
    *nsrc += syncSkip;

    if (err != noErr && err != -74)
556
    {
557 558
        *ndst = *nsrc = 0;
        ERR("Feed Error: %ld\n", err);
559 560 561 562
        return MMSYSERR_ERROR;
    }

    *ndst = amd->outBuffer.mBuffers[0].mDataByteSize;
563 564

    TRACE("convert %d -> %d\n", *nsrc, *ndst);
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596

    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           MPEG3_Reset
 *
 */
static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad)
{
    AudioConverterReset(aad->acr);
}

/***********************************************************************
 *           MPEG3_StreamOpen
 *
 */
static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi)
{
    AcmMpeg3Data* aad;

    assert(!(adsi->fdwOpen & ACM_STREAMOPENF_ASYNC));

    if (MPEG3_GetFormatIndex(adsi->pwfxSrc) == 0xFFFFFFFF ||
        MPEG3_GetFormatIndex(adsi->pwfxDst) == 0xFFFFFFFF)
        return ACMERR_NOTPOSSIBLE;

    aad = HeapAlloc(GetProcessHeap(), 0, sizeof(AcmMpeg3Data));
    if (aad == 0) return MMSYSERR_NOMEM;

    adsi->dwDriver = (DWORD_PTR)aad;

597 598
    if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
         adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
        adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
    {
        OSStatus err;

        aad->in.mSampleRate = adsi->pwfxSrc->nSamplesPerSec;
        aad->out.mSampleRate = adsi->pwfxDst->nSamplesPerSec;
        aad->in.mBitsPerChannel = adsi->pwfxSrc->wBitsPerSample;
        aad->out.mBitsPerChannel = adsi->pwfxDst->wBitsPerSample;
        aad->in.mFormatID = kAudioFormatMPEGLayer3;
        aad->out.mFormatID = kAudioFormatLinearPCM;
        aad->in.mChannelsPerFrame = adsi->pwfxSrc->nChannels;
        aad->out.mChannelsPerFrame = adsi->pwfxDst->nChannels;
        aad->in.mFormatFlags = 0;
        aad->out.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger;
        aad->in.mBytesPerFrame = 0;
        aad->out.mBytesPerFrame = (aad->out.mBitsPerChannel * aad->out.mChannelsPerFrame) / 8;
        aad->in.mBytesPerPacket =  0;
        aad->out.mBytesPerPacket = aad->out.mBytesPerFrame;
        aad->in.mFramesPerPacket = 0;
        aad->out.mFramesPerPacket = 1;
        aad->in.mReserved = aad->out.mReserved = 0;

621 622 623
        aad->tagBytesLeft = -1;

        aad->convert = mp3_leopard_horse;
624

625
        err = AudioConverterNew(&aad->in, &aad->out, &aad->acr);
626 627
        if (err != noErr)
        {
628
            ERR("Create failed: %ld\n", err);
629 630 631
        }
        else
        {
632 633 634
            MPEG3_Reset(adsi, aad);

            return MMSYSERR_NOERROR;
635 636 637 638
        }
    }

    HeapFree(GetProcessHeap(), 0, aad);
639 640
    adsi->dwDriver = 0;

641 642 643 644 645 646 647 648 649
    return MMSYSERR_NOTSUPPORTED;
}

/***********************************************************************
 *           MPEG3_StreamClose
 *
 */
static LRESULT MPEG3_StreamClose(PACMDRVSTREAMINSTANCE adsi)
{
650 651 652 653 654 655 656
    AcmMpeg3Data* amd = (AcmMpeg3Data*)adsi->dwDriver;

    AudioConverterDispose(amd->acr);

    HeapFree(GetProcessHeap(), 0, amd);
    adsi->dwDriver = 0;

657 658 659 660 661
    return MMSYSERR_NOERROR;
}

#endif

662 663 664 665 666 667 668 669
/***********************************************************************
 *           MPEG3_DriverDetails
 *
 */
static	LRESULT MPEG3_DriverDetails(PACMDRIVERDETAILSW add)
{
    add->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
    add->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
670 671
    add->wMid = MM_FRAUNHOFER_IIS;
    add->wPid = MM_FHGIIS_MPEGLAYER3_DECODE;
672 673 674
    add->vdwACM = 0x01000000;
    add->vdwDriver = 0x01000000;
    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 680 681
                         add->szShortName, sizeof(add->szShortName)/sizeof(WCHAR) );
    MultiByteToWideChar( CP_ACP, 0, "Wine MPEG3 decoder", -1,
                         add->szLongName, sizeof(add->szLongName)/sizeof(WCHAR) );
682
    MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
683 684 685 686
                         add->szCopyright, sizeof(add->szCopyright)/sizeof(WCHAR) );
    MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
                         add->szLicensing, sizeof(add->szLicensing)/sizeof(WCHAR) );
    add->szFeatures[0] = 0;
687

688 689 690 691 692 693 694 695 696
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           MPEG3_FormatTagDetails
 *
 */
static	LRESULT	MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery)
{
697 698
    static const WCHAR szPcm[]={'P','C','M',0};
    static const WCHAR szMpeg3[]={'M','P','e','g','3',0};
699
    static const WCHAR szMpeg[]={'M','P','e','g',0};
700 701

    switch (dwQuery)
702 703
    {
    case ACM_FORMATTAGDETAILSF_INDEX:
704
	if (aftd->dwFormatTagIndex > 2) return ACMERR_NOTPOSSIBLE;
705 706
	break;
    case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
707
	if (aftd->dwFormatTag == WAVE_FORMAT_UNKNOWN)
708
        {
709
            aftd->dwFormatTagIndex = 2; /* WAVE_FORMAT_MPEG is biggest */
710 711
	    break;
	}
712
	/* fall through */
713 714
    case ACM_FORMATTAGDETAILSF_FORMATTAG:
	switch (aftd->dwFormatTag)
715 716 717
        {
	case WAVE_FORMAT_PCM:		aftd->dwFormatTagIndex = 0; break;
	case WAVE_FORMAT_MPEGLAYER3:    aftd->dwFormatTagIndex = 1; break;
718
	case WAVE_FORMAT_MPEG:          aftd->dwFormatTagIndex = 2; break;
719 720 721 722
	default:			return ACMERR_NOTPOSSIBLE;
	}
	break;
    default:
723
	WARN("Unsupported query %08x\n", dwQuery);
724 725
	return MMSYSERR_NOTSUPPORTED;
    }
726

727
    aftd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
728
    switch (aftd->dwFormatTagIndex)
729 730 731 732
    {
    case 0:
	aftd->dwFormatTag = WAVE_FORMAT_PCM;
	aftd->cbFormatSize = sizeof(PCMWAVEFORMAT);
733
	aftd->cStandardFormats = ARRAY_SIZE(PCM_Formats);
734 735 736 737 738
        lstrcpyW(aftd->szFormatTag, szPcm);
        break;
    case 1:
	aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3;
	aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT);
739
        aftd->cStandardFormats = 0;
740 741
        lstrcpyW(aftd->szFormatTag, szMpeg3);
	break;
742 743 744
    case 2:
	aftd->dwFormatTag = WAVE_FORMAT_MPEG;
	aftd->cbFormatSize = sizeof(MPEG1WAVEFORMAT);
745
        aftd->cStandardFormats = 0;
746 747
        lstrcpyW(aftd->szFormatTag, szMpeg);
	break;
748 749 750 751 752 753 754 755 756 757
    }
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           MPEG3_FormatDetails
 *
 */
static	LRESULT	MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery)
{
758
    switch (dwQuery)
759 760 761 762 763 764
    {
    case ACM_FORMATDETAILSF_FORMAT:
	if (MPEG3_GetFormatIndex(afd->pwfx) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
	break;
    case ACM_FORMATDETAILSF_INDEX:
	afd->pwfx->wFormatTag = afd->dwFormatTag;
765
	switch (afd->dwFormatTag)
766 767
        {
	case WAVE_FORMAT_PCM:
768
	    if (afd->dwFormatIndex >= ARRAY_SIZE(PCM_Formats)) return ACMERR_NOTPOSSIBLE;
769 770 771 772
	    afd->pwfx->nChannels = PCM_Formats[afd->dwFormatIndex].nChannels;
	    afd->pwfx->nSamplesPerSec = PCM_Formats[afd->dwFormatIndex].rate;
	    afd->pwfx->wBitsPerSample = PCM_Formats[afd->dwFormatIndex].nBits;
	    /* native MSACM uses a PCMWAVEFORMAT structure, so cbSize is not accessible
773
	     * afd->pwfx->cbSize = 0;
774
	     */
775
	    afd->pwfx->nBlockAlign =
776
		(afd->pwfx->nChannels * afd->pwfx->wBitsPerSample) / 8;
777
	    afd->pwfx->nAvgBytesPerSec =
778 779 780
		afd->pwfx->nSamplesPerSec * afd->pwfx->nBlockAlign;
	    break;
	case WAVE_FORMAT_MPEGLAYER3:
781
	case WAVE_FORMAT_MPEG:
782 783
            WARN("Encoding to MPEG is not supported\n");
            return ACMERR_NOTPOSSIBLE;
784
	default:
785
            WARN("Unsupported tag %08x\n", afd->dwFormatTag);
786 787 788 789
	    return MMSYSERR_INVALPARAM;
	}
	break;
    default:
790
	WARN("Unsupported query %08x\n", dwQuery);
791
	return MMSYSERR_NOTSUPPORTED;
792 793 794
    }
    afd->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
    afd->szFormat[0] = 0; /* let MSACM format this for us... */
795

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           MPEG3_FormatSuggest
 *
 */
static	LRESULT	MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs)
{
    /* some tests ... */
    if (adfs->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
	adfs->cbwfxDst < sizeof(PCMWAVEFORMAT) ||
	MPEG3_GetFormatIndex(adfs->pwfxSrc) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;
    /* FIXME: should do those tests against the real size (according to format tag */

    /* If no suggestion for destination, then copy source value */
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS))
	adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels;
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC))
        adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec;
816
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE))
817
        adfs->pwfxDst->wBitsPerSample = 16;
818
    if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG))
819
    {
820
	if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM)
821 822 823 824
        {
            WARN("Encoding to MPEG is not supported\n");
            return ACMERR_NOTPOSSIBLE;
        }
825 826 827
        else
            adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM;
    }
828

829 830 831 832 833 834 835 836 837 838
    /* check if result is ok */
    if (MPEG3_GetFormatIndex(adfs->pwfxDst) == 0xFFFFFFFF) return ACMERR_NOTPOSSIBLE;

    /* recompute other values */
    switch (adfs->pwfxDst->wFormatTag)
    {
    case WAVE_FORMAT_PCM:
        adfs->pwfxDst->nBlockAlign = (adfs->pwfxDst->nChannels * adfs->pwfxDst->wBitsPerSample) / 8;
        adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign;
        break;
839
    case WAVE_FORMAT_MPEG:
840
    case WAVE_FORMAT_MPEGLAYER3:
841 842
        WARN("Encoding to MPEG is not supported\n");
        return ACMERR_NOTPOSSIBLE;
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
        break;
    default:
        FIXME("\n");
        break;
    }

    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           MPEG3_StreamSize
 *
 */
static	LRESULT MPEG3_StreamSize(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMSIZE adss)
{
858 859
    DWORD nblocks;

860
    switch (adss->fdwSize)
861 862 863 864
    {
    case ACM_STREAMSIZEF_DESTINATION:
	/* cbDstLength => cbSrcLength */
	if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
865 866
            (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
867
        {
868
            nblocks = (adss->cbDstLength - 3000) / (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
869 870 871
            if (nblocks == 0)
                return ACMERR_NOTPOSSIBLE;
            adss->cbSrcLength = nblocks * 1152 * adsi->pwfxSrc->nBlockAlign;
872
	}
873 874
        else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
                 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
875
                 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
876
        {
877 878 879
            nblocks = adss->cbDstLength / (adsi->pwfxDst->nBlockAlign * 1152);
            if (nblocks == 0)
                return ACMERR_NOTPOSSIBLE;
880
            adss->cbSrcLength = nblocks * (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
881
	}
882
        else
883 884 885 886 887 888 889
        {
	    return MMSYSERR_NOTSUPPORTED;
	}
	break;
    case ACM_STREAMSIZEF_SOURCE:
	/* cbSrcLength => cbDstLength */
	if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM &&
890 891
            (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
             adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG))
892
        {
893
            nblocks = adss->cbSrcLength / (adsi->pwfxSrc->nBlockAlign * 1152);
894 895 896
            if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nBlockAlign * 1152))
                /* Round block count up. */
                nblocks++;
897 898
            if (nblocks == 0)
                return ACMERR_NOTPOSSIBLE;
899
            adss->cbDstLength = 3000 + nblocks * (DWORD)(adsi->pwfxDst->nAvgBytesPerSec * 1152 / adsi->pwfxDst->nSamplesPerSec + 0.5);
900
	}
901 902
        else if ((adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3 ||
                 adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) &&
903
                 adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM)
904
        {
905 906 907 908
            nblocks = adss->cbSrcLength / (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec);
            if (adss->cbSrcLength % (DWORD)(adsi->pwfxSrc->nAvgBytesPerSec * 1152 / adsi->pwfxSrc->nSamplesPerSec))
                /* Round block count up. */
                nblocks++;
909 910
            if (nblocks == 0)
                return ACMERR_NOTPOSSIBLE;
911
            adss->cbDstLength = nblocks * 1152 * adsi->pwfxDst->nBlockAlign;
912
	}
913
        else
914 915 916 917 918
        {
	    return MMSYSERR_NOTSUPPORTED;
	}
	break;
    default:
919
	WARN("Unsupported query %08x\n", adss->fdwSize);
920
	return MMSYSERR_NOTSUPPORTED;
921 922 923 924 925 926 927 928 929 930 931 932 933
    }
    return MMSYSERR_NOERROR;
}

/***********************************************************************
 *           MPEG3_StreamConvert
 *
 */
static LRESULT MPEG3_StreamConvert(PACMDRVSTREAMINSTANCE adsi, PACMDRVSTREAMHEADER adsh)
{
    AcmMpeg3Data*	aad = (AcmMpeg3Data*)adsi->dwDriver;
    DWORD		nsrc = adsh->cbSrcLength;
    DWORD		ndst = adsh->cbDstLength;
934 935

    if (adsh->fdwConvert &
936 937
	~(ACM_STREAMCONVERTF_BLOCKALIGN|
	  ACM_STREAMCONVERTF_END|
938
	  ACM_STREAMCONVERTF_START))
939
    {
940
	FIXME("Unsupported fdwConvert (%08x), ignoring it\n", adsh->fdwConvert);
941 942 943 944 945 946
    }
    /* ACM_STREAMCONVERTF_BLOCKALIGN
     *	currently all conversions are block aligned, so do nothing for this flag
     * ACM_STREAMCONVERTF_END
     *	no pending data, so do nothing for this flag
     */
947
    if ((adsh->fdwConvert & ACM_STREAMCONVERTF_START))
948
    {
949
        MPEG3_Reset(adsi, aad);
950 951 952 953 954
    }

    aad->convert(adsi, adsh->pbSrc, &nsrc, adsh->pbDst, &ndst);
    adsh->cbSrcLengthUsed = nsrc;
    adsh->cbDstLengthUsed = ndst;
955

956 957 958 959 960 961
    return MMSYSERR_NOERROR;
}

/**************************************************************************
 * 			MPEG3_DriverProc			[exported]
 */
962
LRESULT CALLBACK MPEG3_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
963 964
					 LPARAM dwParam1, LPARAM dwParam2)
{
965 966
    TRACE("(%08lx %p %04x %08lx %08lx);\n",
	  dwDevID, hDriv, wMsg, dwParam1, dwParam2);
967 968

    switch (wMsg)
969 970 971 972 973
    {
    case DRV_LOAD:		return 1;
    case DRV_FREE:		return 1;
    case DRV_OPEN:		return MPEG3_drvOpen((LPSTR)dwParam1);
    case DRV_CLOSE:		return MPEG3_drvClose(dwDevID);
974
    case DRV_ENABLE:		return 1;
975 976 977 978 979
    case DRV_DISABLE:		return 1;
    case DRV_QUERYCONFIGURE:	return 1;
    case DRV_CONFIGURE:		MessageBoxA(0, "MPEG3 filter !", "Wine Driver", MB_OK); return 1;
    case DRV_INSTALL:		return DRVCNF_RESTART;
    case DRV_REMOVE:		return DRVCNF_RESTART;
980

981 982 983
    case ACMDM_DRIVER_NOTIFY:
	/* no caching from other ACM drivers is done so far */
	return MMSYSERR_NOERROR;
984

985 986
    case ACMDM_DRIVER_DETAILS:
	return MPEG3_DriverDetails((PACMDRIVERDETAILSW)dwParam1);
987

988 989
    case ACMDM_FORMATTAG_DETAILS:
	return MPEG3_FormatTagDetails((PACMFORMATTAGDETAILSW)dwParam1, dwParam2);
990

991 992
    case ACMDM_FORMAT_DETAILS:
	return MPEG3_FormatDetails((PACMFORMATDETAILSW)dwParam1, dwParam2);
993

994 995
    case ACMDM_FORMAT_SUGGEST:
	return MPEG3_FormatSuggest((PACMDRVFORMATSUGGEST)dwParam1);
996

997 998
    case ACMDM_STREAM_OPEN:
	return MPEG3_StreamOpen((PACMDRVSTREAMINSTANCE)dwParam1);
999

1000 1001
    case ACMDM_STREAM_CLOSE:
	return MPEG3_StreamClose((PACMDRVSTREAMINSTANCE)dwParam1);
1002

1003 1004
    case ACMDM_STREAM_SIZE:
	return MPEG3_StreamSize((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMSIZE)dwParam2);
1005

1006 1007
    case ACMDM_STREAM_CONVERT:
	return MPEG3_StreamConvert((PACMDRVSTREAMINSTANCE)dwParam1, (PACMDRVSTREAMHEADER)dwParam2);
1008

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
    case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
    case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
	/* this converter is not a hardware driver */
    case ACMDM_FILTERTAG_DETAILS:
    case ACMDM_FILTER_DETAILS:
	/* this converter is not a filter */
    case ACMDM_STREAM_RESET:
	/* only needed for asynchronous driver... we aren't, so just say it */
	return MMSYSERR_NOTSUPPORTED;
    case ACMDM_STREAM_PREPARE:
    case ACMDM_STREAM_UNPREPARE:
	/* nothing special to do here... so don't do anything */
	return MMSYSERR_NOERROR;
1022

1023 1024 1025 1026
    default:
	return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
    }
}