VirtualBox

Changeset 89423 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 1, 2021 10:14:16 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144776
Message:

DrvHostAudioPulseAudio: Multi channel support. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostAudioPulseAudio.cpp

    r89258 r89423  
    141141    /** Pointer to opaque PulseAudio stream. */
    142142    pa_stream              *pStream;
    143     /** Pulse sample format and attribute specification. */
    144     pa_sample_spec          SampleSpec;
    145     /** Pulse playback and buffer metrics. */
    146     pa_buffer_attr          BufAttr;
    147143    /** Input: Pointer to Pulse sample peek buffer. */
    148144    const uint8_t          *pbPeekBuf;
     
    175171    uint32_t                cUnderflows;
    176172#endif
     173    /** Pulse sample format and attribute specification. */
     174    pa_sample_spec          SampleSpec;
     175    /** Channel map. */
     176    pa_channel_map          ChannelMap;
     177    /** Pulse playback and buffer metrics. */
     178    pa_buffer_attr          BufAttr;
    177179} PULSEAUDIOSTREAM;
    178180/** Pointer to pulse audio stream data. */
     
    905907     * Create the stream.
    906908     */
    907     pa_stream *pStream = pa_stream_new(pThis->pContext, pszName, &pStreamPA->SampleSpec, NULL /* pa_channel_map */);
     909    pa_stream *pStream = pa_stream_new(pThis->pContext, pszName, &pStreamPA->SampleSpec, &pStreamPA->ChannelMap);
    908910    if (!pStream)
    909911    {
     
    10221024
    10231025/**
     1026 * Translates a PDM channel ID to a PA channel position.
     1027 *
     1028 * @returns PA channel position, INVALID if no mapping found.
     1029 */
     1030static pa_channel_position_t drvHstAudPaConvertChannelId(uint8_t idChannel)
     1031{
     1032    switch (idChannel)
     1033    {
     1034        case PDMAUDIOCHANNELID_FRONT_LEFT:              return PA_CHANNEL_POSITION_FRONT_LEFT;
     1035        case PDMAUDIOCHANNELID_FRONT_RIGHT:             return PA_CHANNEL_POSITION_FRONT_RIGHT;
     1036        case PDMAUDIOCHANNELID_FRONT_CENTER:            return PA_CHANNEL_POSITION_FRONT_CENTER;
     1037        case PDMAUDIOCHANNELID_LFE:                     return PA_CHANNEL_POSITION_LFE;
     1038        case PDMAUDIOCHANNELID_REAR_LEFT:               return PA_CHANNEL_POSITION_REAR_LEFT;
     1039        case PDMAUDIOCHANNELID_REAR_RIGHT:              return PA_CHANNEL_POSITION_REAR_RIGHT;
     1040        case PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER:    return PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
     1041        case PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER:   return PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
     1042        case PDMAUDIOCHANNELID_REAR_CENTER:             return PA_CHANNEL_POSITION_REAR_CENTER;
     1043        case PDMAUDIOCHANNELID_SIDE_LEFT:               return PA_CHANNEL_POSITION_SIDE_LEFT;
     1044        case PDMAUDIOCHANNELID_SIDE_RIGHT:              return PA_CHANNEL_POSITION_SIDE_RIGHT;
     1045        case PDMAUDIOCHANNELID_TOP_CENTER:              return PA_CHANNEL_POSITION_TOP_CENTER;
     1046        case PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT:       return PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
     1047        case PDMAUDIOCHANNELID_FRONT_CENTER_HEIGHT:     return PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
     1048        case PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT:      return PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
     1049        case PDMAUDIOCHANNELID_REAR_LEFT_HEIGHT:        return PA_CHANNEL_POSITION_TOP_REAR_LEFT;
     1050        case PDMAUDIOCHANNELID_REAR_CENTER_HEIGHT:      return PA_CHANNEL_POSITION_TOP_REAR_CENTER;
     1051        case PDMAUDIOCHANNELID_REAR_RIGHT_HEIGHT:       return PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
     1052        default:                                        return PA_CHANNEL_POSITION_INVALID;
     1053    }
     1054}
     1055
     1056
     1057/**
     1058 * Translates a PA channel position to a PDM channel ID.
     1059 *
     1060 * @returns PDM channel ID, UNKNOWN if no mapping found.
     1061 */
     1062static PDMAUDIOCHANNELID drvHstAudPaConvertChannelPos(pa_channel_position_t enmChannelPos)
     1063{
     1064    switch (enmChannelPos)
     1065    {
     1066        case PA_CHANNEL_POSITION_INVALID:               return PDMAUDIOCHANNELID_INVALID;
     1067        case PA_CHANNEL_POSITION_MONO:                  return PDMAUDIOCHANNELID_MONO;
     1068        case PA_CHANNEL_POSITION_FRONT_LEFT:            return PDMAUDIOCHANNELID_FRONT_LEFT;
     1069        case PA_CHANNEL_POSITION_FRONT_RIGHT:           return PDMAUDIOCHANNELID_FRONT_RIGHT;
     1070        case PA_CHANNEL_POSITION_FRONT_CENTER:          return PDMAUDIOCHANNELID_FRONT_CENTER;
     1071        case PA_CHANNEL_POSITION_LFE:                   return PDMAUDIOCHANNELID_LFE;
     1072        case PA_CHANNEL_POSITION_REAR_LEFT:             return PDMAUDIOCHANNELID_REAR_LEFT;
     1073        case PA_CHANNEL_POSITION_REAR_RIGHT:            return PDMAUDIOCHANNELID_REAR_RIGHT;
     1074        case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:  return PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER;
     1075        case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: return PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER;
     1076        case PA_CHANNEL_POSITION_REAR_CENTER:           return PDMAUDIOCHANNELID_REAR_CENTER;
     1077        case PA_CHANNEL_POSITION_SIDE_LEFT:             return PDMAUDIOCHANNELID_SIDE_LEFT;
     1078        case PA_CHANNEL_POSITION_SIDE_RIGHT:            return PDMAUDIOCHANNELID_SIDE_RIGHT;
     1079        case PA_CHANNEL_POSITION_TOP_CENTER:            return PDMAUDIOCHANNELID_TOP_CENTER;
     1080        case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:        return PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT;
     1081        case PA_CHANNEL_POSITION_TOP_FRONT_CENTER:      return PDMAUDIOCHANNELID_FRONT_CENTER_HEIGHT;
     1082        case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:       return PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT;
     1083        case PA_CHANNEL_POSITION_TOP_REAR_LEFT:         return PDMAUDIOCHANNELID_REAR_LEFT_HEIGHT;
     1084        case PA_CHANNEL_POSITION_TOP_REAR_CENTER:       return PDMAUDIOCHANNELID_REAR_CENTER_HEIGHT;
     1085        case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:        return PDMAUDIOCHANNELID_REAR_RIGHT_HEIGHT;
     1086        default:                                        return PDMAUDIOCHANNELID_UNKNOWN;
     1087    }
     1088}
     1089
     1090
     1091
     1092/**
    10241093 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate}
    10251094 */
     
    10491118    pStreamPA->SampleSpec.format   = drvHostAudioPaPropsToPulse(&pCfgReq->Props);
    10501119
    1051     LogFunc(("Opening '%s', rate=%dHz, channels=%d, format=%s\n", szName, pStreamPA->SampleSpec.rate,
    1052              pStreamPA->SampleSpec.channels, pa_sample_format_to_string(pStreamPA->SampleSpec.format)));
     1120    /*
     1121     * Initialize the channelmap.  This may change the channel count.
     1122     */
     1123    AssertCompile(RT_ELEMENTS(pStreamPA->ChannelMap.map) >= PDMAUDIO_MAX_CHANNELS);
     1124    uint8_t const cSrcChannels = pStreamPA->ChannelMap.channels = PDMAudioPropsChannels(&pCfgReq->Props);
     1125    uintptr_t iDst = 0;
     1126    if (cSrcChannels == 1 && pCfgReq->Props.aidChannels[0] == PDMAUDIOCHANNELID_MONO)
     1127        pStreamPA->ChannelMap.map[iDst++] = PA_CHANNEL_POSITION_MONO;
     1128    else
     1129    {
     1130        uintptr_t iSrc;
     1131        for (iSrc = iDst = 0; iSrc < cSrcChannels; iSrc++)
     1132        {
     1133            pStreamPA->ChannelMap.map[iDst] = drvHstAudPaConvertChannelId(pCfgReq->Props.aidChannels[iSrc]);
     1134            if (pStreamPA->ChannelMap.map[iDst] != PA_CHANNEL_POSITION_INVALID)
     1135                iDst++;
     1136            else
     1137            {
     1138                LogRel2(("PulseAudio: Dropping channel #%u (%d/%s)\n", iSrc, pCfgReq->Props.aidChannels[iSrc],
     1139                         PDMAudioChannelIdGetName((PDMAUDIOCHANNELID)pCfgReq->Props.aidChannels[iSrc])));
     1140                pStreamPA->ChannelMap.channels--;
     1141                pStreamPA->SampleSpec.channels--;
     1142                PDMAudioPropsSetChannels(&pCfgAcq->Props, pStreamPA->SampleSpec.channels);
     1143            }
     1144        }
     1145        Assert(iDst == pStreamPA->ChannelMap.channels);
     1146    }
     1147    while (iDst < RT_ELEMENTS(pStreamPA->ChannelMap.map))
     1148        pStreamPA->ChannelMap.map[iDst++] = PA_CHANNEL_POSITION_INVALID;
     1149
     1150    LogFunc(("Opening '%s', rate=%dHz, channels=%d (%d), format=%s\n", szName, pStreamPA->SampleSpec.rate,
     1151             pStreamPA->SampleSpec.channels, cSrcChannels, pa_sample_format_to_string(pStreamPA->SampleSpec.format)));
    10531152
    10541153    if (pa_sample_spec_valid(&pStreamPA->SampleSpec))
     
    10641163        if (pCfgReq->enmDir == PDMAUDIODIR_IN)
    10651164        {
    1066             pStreamPA->BufAttr.fragsize  = PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod);
     1165            pStreamPA->BufAttr.fragsize  = PDMAudioPropsFramesToBytes(&pCfgAcq->Props, pCfgReq->Backend.cFramesPeriod);
    10671166            LogFunc(("Requesting: BufAttr: fragsize=%RU32\n", pStreamPA->BufAttr.fragsize));
    10681167            /* (rlength, minreq and prebuf are playback only) */
     
    10701169        else
    10711170        {
    1072             pStreamPA->cUsLatency        = PDMAudioPropsFramesToMicro(&pCfgReq->Props, pCfgReq->Backend.cFramesBufferSize);
     1171            pStreamPA->cUsLatency        = PDMAudioPropsFramesToMicro(&pCfgAcq->Props, pCfgReq->Backend.cFramesBufferSize);
    10731172            pStreamPA->BufAttr.tlength   = pa_usec_to_bytes(pStreamPA->cUsLatency, &pStreamPA->SampleSpec);
    1074             pStreamPA->BufAttr.minreq    = PDMAudioPropsFramesToBytes(&pCfgReq->Props, pCfgReq->Backend.cFramesPeriod);
    1075             pStreamPA->BufAttr.prebuf    = pa_usec_to_bytes(PDMAudioPropsFramesToMicro(&pCfgReq->Props,
     1173            pStreamPA->BufAttr.minreq    = PDMAudioPropsFramesToBytes(&pCfgAcq->Props, pCfgReq->Backend.cFramesPeriod);
     1174            pStreamPA->BufAttr.prebuf    = pa_usec_to_bytes(PDMAudioPropsFramesToMicro(&pCfgAcq->Props,
    10761175                                                                                       pCfgReq->Backend.cFramesPreBuffering),
    10771176                                                            &pStreamPA->SampleSpec);
     
    11111210                                                      / RT_MAX(pCfgReq->Backend.cFramesBufferSize, 1);
    11121211            }
     1212
     1213            /*
     1214             * Translate back the channel mapping.
     1215             */
     1216            for (iDst = 0; iDst < pStreamPA->ChannelMap.channels; iDst++)
     1217                 pCfgReq->Props.aidChannels[iDst] = drvHstAudPaConvertChannelPos(pStreamPA->ChannelMap.map[iDst]);
     1218            while (iDst < RT_ELEMENTS(pCfgReq->Props.aidChannels))
     1219                pCfgReq->Props.aidChannels[iDst++] = PDMAUDIOCHANNELID_INVALID;
     1220
    11131221            PDMAudioStrmCfgCopy(&pStreamPA->Cfg, pCfgAcq);
    11141222        }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette