Ticket #6538: aowin_trunk.patch

File aowin_trunk.patch, 6.2 KB (added by Jeff Lu <jll544@…>, 15 years ago)

This patch adds SPDIF and 5.1 to audio_win, giving DirectX and Windows similar features (except for Creative Labs drivers as noted above)

  • libs/libmyth/audiooutputwin.h

     
    2929    long                   m_nPkts;
    3030    int                    m_CurrentPkt;
    3131    unsigned char        **m_OutPkts;
     32    bool                   m_UseSPDIF;
    3233
    3334    static const uint      kPacketCnt;
    3435};
  • libs/libmyth/audiooutputwin.cpp

     
    99#include <windows.h>
    1010#include <mmsystem.h>
    1111
     12/*****************************************************************************
     13 * Useful macros
     14 *****************************************************************************/
     15#ifndef WAVE_FORMAT_IEEE_FLOAT
     16#   define WAVE_FORMAT_IEEE_FLOAT 0x0003
     17#endif
     18
     19#ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
     20#   define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
     21#endif
     22
     23#ifndef WAVE_FORMAT_EXTENSIBLE
     24#define  WAVE_FORMAT_EXTENSIBLE   0xFFFE
     25#endif
     26
     27#ifndef _WAVEFORMATEXTENSIBLE_
     28typedef struct {
     29    WAVEFORMATEX    Format;
     30    union {
     31        WORD wValidBitsPerSample;       /* bits of precision  */
     32        WORD wSamplesPerBlock;          /* valid if wBitsPerSample==0 */
     33        WORD wReserved;                 /* If neither applies, set to zero. */
     34    } Samples;
     35    DWORD           dwChannelMask;      /* which channels are */
     36                                        /* present in stream  */
     37    GUID            SubFormat;
     38} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
     39#endif
     40
     41DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
     42DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_PCM, WAVE_FORMAT_PCM, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
     43DEFINE_GUID( _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF, WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 );
     44
    1245// even number, 42 ~= 1.008 sec @ 48000 with 1152 samples per packet
    1346const uint AudioOutputWin::kPacketCnt = 16;
    1447
     
    1649{
    1750  public:
    1851    AudioOutputWinPrivate() :
    19         m_WaveHdrs(NULL), m_hEvent(NULL)
     52        m_hWaveOut(NULL), m_WaveHdrs(NULL), m_hEvent(NULL)
    2053    {
    2154        m_WaveHdrs = new WAVEHDR[AudioOutputWin::kPacketCnt];
    2255        memset(m_WaveHdrs, 0, sizeof(WAVEHDR) * AudioOutputWin::kPacketCnt);
     
    76109    m_priv(new AudioOutputWinPrivate()),
    77110    m_nPkts(0),
    78111    m_CurrentPkt(0),
    79     m_OutPkts(NULL)
     112    m_OutPkts(NULL),
     113    m_UseSPDIF(settings.use_passthru)
    80114{
    81115    Reconfigure(settings);
    82116
     
    111145    // Set everything up
    112146    SetBlocking(true);
    113147    fragment_size = (AUDIOOUTPUT_TELEPHONY == source) ? 320 : 6144;
     148    soundcard_buffer_size = kPacketCnt * fragment_size;
    114149
    115     WAVEFORMATEX wf;
    116     wf.wFormatTag = WAVE_FORMAT_PCM;
    117     wf.nChannels = audio_channels;
    118     wf.nSamplesPerSec = audio_samplerate;
    119     wf.wBitsPerSample = audio_bits;
    120     wf.nBlockAlign = wf.wBitsPerSample / 8 * wf.nChannels;
    121     wf.nAvgBytesPerSec = wf.nBlockAlign * wf.nSamplesPerSec;
    122     wf.cbSize = 0;
     150    WAVEFORMATEXTENSIBLE wf;
     151    wf.Format.wFormatTag =
     152        (m_UseSPDIF) ? WAVE_FORMAT_DOLBY_AC3_SPDIF : WAVE_FORMAT_PCM;
     153    wf.Format.nChannels = audio_channels;
     154    wf.Format.nSamplesPerSec = audio_samplerate;
     155    wf.Format.nBlockAlign = audio_bytes_per_sample;
     156    wf.Format.nAvgBytesPerSec =
     157        wf.Format.nSamplesPerSec * wf.Format.nBlockAlign;
     158    wf.Format.wBitsPerSample = audio_bits;
     159    wf.Samples.wValidBitsPerSample = wf.Format.wBitsPerSample;
     160    wf.SubFormat =
     161        (m_UseSPDIF) ? _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF : _KSDATAFORMAT_SUBTYPE_PCM;
    123162
     163    VERBOSE(VB_AUDIO, "New format: " << audio_bits << "bits, "
     164            << audio_channels << "ch, " << audio_samplerate << "Hz");
     165
     166    /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
     167    if (audio_channels <= 2)
     168    {
     169        wf.Format.cbSize = 0;
     170    }
     171    else
     172    {
     173        wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
     174        wf.dwChannelMask = 0x003F;          // 0x003F = 5.1 channels
     175        wf.Format.cbSize =
     176            sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
     177    }
     178
    124179    MMRESULT mmr = waveOutOpen(
    125180        &m_priv->m_hWaveOut,
    126181        WAVE_MAPPER,
    127         &wf,
     182        (WAVEFORMATEX *)&wf,
    128183        (DWORD) AudioOutputWinPrivate::waveOutProc,
    129184        (DWORD) this,
    130185        CALLBACK_FUNCTION);
     
    132187    if (mmr == WAVERR_BADFORMAT)
    133188    {
    134189        Error(QString("Unable to set audio output parameters %1")
    135               .arg(wf.nSamplesPerSec));
     190              .arg(wf.Format.nSamplesPerSec));
    136191        return false;
    137192    }
    138193
     
    149204    if (size == 0)
    150205        return;
    151206
    152     if (InterlockedIncrement(&m_nPkts) >= kPacketCnt)
     207    if (audio_channels == 6)
    153208    {
    154         while (m_nPkts >= kPacketCnt)
     209        // Linux and Windows have different 5.1 channel order conventions
     210        const uint kReorder[6] = {0,1,4,5,2,3};
     211        int abytes = audio_bits / 8;
     212        unsigned char p_tmp[24];
     213        unsigned char *obuf = buffer;
     214        for(int i = 0; i < size / audio_channels / abytes; i++)
     215        {
     216            for(int j = 0; j < audio_channels; j++)
     217            {
     218                for(int k = 0; k < abytes; k++)
     219                {
     220                    p_tmp[abytes * kReorder[j] + k] = buffer[abytes * j + k];
     221                }
     222            }
     223            memcpy(buffer, p_tmp, abytes * audio_channels);
     224            buffer += abytes * audio_channels;
     225        }
     226        buffer = obuf;
     227    }
     228
     229    if (InterlockedIncrement(&m_nPkts) > kPacketCnt)
     230    {
     231        while (m_nPkts > kPacketCnt)
    155232            WaitForSingleObject(m_priv->m_hEvent, INFINITE);
    156233    }
    157234
     
    187264
    188265int AudioOutputWin::GetSpaceOnSoundcard(void) const
    189266{
    190     return (kPacketCnt - m_nPkts) * 1536 * 4;
     267    return soundcard_buffer_size - GetBufferedOnSoundcard();
    191268}
    192269
    193270int AudioOutputWin::GetBufferedOnSoundcard(void) const
    194271{
    195     return m_nPkts * 1536 * 4;
     272    return m_nPkts * fragment_size;
    196273}
    197274
    198275int AudioOutputWin::GetVolumeChannel(int channel) const