Changeset 67365 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Jun 13, 2017 2:17:59 PM (8 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r65739 r67365 62 62 63 63 #ifdef DEBUG 64 DECLINLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf); 64 DECLINLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc); 65 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf); 65 66 #endif 66 67 … … 134 135 AssertCompile(AUDIOMIXBUF_VOL_0DB == 0x40000000); /* For now -- when only attenuation is used. */ 135 136 136 #ifdef DEBUG137 static uint64_t s_cSamplesMixedTotal = 0;138 #endif139 140 137 141 138 /** … … 288 285 289 286 pIter->cMixed -= RT_MIN(pIter->cMixed, cSamplesToClear); 290 pIter->cUsed -= RT_MIN(pIter->cUsed, AUDIOMIXBUF_S2S_RATIO(pMixBuf, cSamplesToClear));287 /* Note: Do not increment pIter->cUsed here, as this gets done when reading from that buffer using AudioMixBufReadXXX. */ 291 288 } 292 289 … … 822 819 823 820 pMixBuf->pParent = NULL; 821 824 822 RTListInit(&pMixBuf->lstChildren); 823 pMixBuf->cChildren = 0; 825 824 826 825 pMixBuf->pSamples = NULL; … … 883 882 884 883 /** 884 * Calculates the frequency (sample rate) ratio of mixing buffer A in relation to mixing buffer B. 885 * 886 * @returns Calculated frequency ratio. 887 * @param pMixBufA First mixing buffer. 888 * @param pMixBufB Second mixing buffer. 889 */ 890 static int64_t audioMixBufCalcFreqRatio(PPDMAUDIOMIXBUF pMixBufA, PPDMAUDIOMIXBUF pMixBufB) 891 { 892 int64_t iRatio = ((int64_t)AUDMIXBUF_FMT_SAMPLE_FREQ(pMixBufA->AudioFmt) << 32) 893 / AUDMIXBUF_FMT_SAMPLE_FREQ(pMixBufB->AudioFmt); 894 895 if (iRatio == 0) /* Catch division by zero. */ 896 iRatio = 1 << 20; /* Do a 1:1 conversion instead. */ 897 898 return iRatio; 899 } 900 901 /** 885 902 * Links an audio mixing buffer to a parent mixing buffer. A parent mixing 886 903 * buffer can have multiple children mixing buffers [1:N], whereas a child only can … … 922 939 923 940 RTListAppend(&pParent->lstChildren, &pMixBuf->Node); 941 pParent->cChildren++; 942 943 /* Set the parent. */ 924 944 pMixBuf->pParent = pParent; 925 945 926 /* Calculate the frequency ratio. */ 927 pMixBuf->iFreqRatio = ((int64_t)AUDMIXBUF_FMT_SAMPLE_FREQ(pParent->AudioFmt) << 32) 928 / AUDMIXBUF_FMT_SAMPLE_FREQ(pMixBuf->AudioFmt); 929 930 if (pMixBuf->iFreqRatio == 0) /* Catch division by zero. */ 931 pMixBuf->iFreqRatio = 1 << 20; /* Do a 1:1 conversion instead. */ 946 /* Calculate the frequency ratios. */ 947 pMixBuf->iFreqRatio = audioMixBufCalcFreqRatio(pParent, pMixBuf); 932 948 933 949 int rc = VINF_SUCCESS; … … 1044 1060 * @param pDst Destination mixing buffer. 1045 1061 * @param pSrc Source mixing buffer. 1062 * @param cSrcOff Offset of source audio samples to mix. 1046 1063 * @param cSrcSamples Number of source audio samples to mix. 1047 * @param pcProcessed Number of audio samples successfully mixed. 1048 */ 1049 static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSrcSamples, uint32_t *pcProcessed) 1064 * @param pcSrcMixed Number of source audio samples successfully mixed. Optional. 1065 */ 1066 static int audioMixBufMixTo(PPDMAUDIOMIXBUF pDst, PPDMAUDIOMIXBUF pSrc, uint32_t cSrcOff, uint32_t cSrcSamples, 1067 uint32_t *pcSrcMixed) 1050 1068 { 1051 1069 AssertPtrReturn(pDst, VERR_INVALID_POINTER); 1052 1070 AssertPtrReturn(pSrc, VERR_INVALID_POINTER); 1053 /* pc Processed is optional. */1071 /* pcSrcMixed is optional. */ 1054 1072 1055 1073 AssertMsgReturn(pDst == pSrc->pParent, ("Source buffer '%s' is not a child of destination '%s'\n", … … 1058 1076 uint32_t cWrittenTotal = 0; 1059 1077 1060 if (pSrc->cMixed >= pDst->cSamples) 1061 { 1062 AUDMIXBUF_LOG(("Warning: Destination buffer '%s' full (%RU32 samples max), got %RU32 mixed samples\n", 1063 pDst->pszName, pDst->cSamples, pSrc->cMixed)); 1064 if (pcProcessed) 1065 *pcProcessed = 0; 1078 Assert(pSrc->cMixed <= pDst->cSamples); 1079 1080 Assert(pSrc->cUsed >= pDst->cMixed); 1081 Assert(pDst->cUsed <= pDst->cSamples); 1082 1083 uint32_t offSrcRead = cSrcOff; 1084 1085 uint32_t offDstWrite = pDst->offWrite; 1086 uint32_t cDstMixed = pSrc->cMixed; 1087 1088 uint32_t cSrcAvail = RT_MIN(cSrcSamples, pSrc->cUsed); 1089 uint32_t cDstAvail = pDst->cSamples - pDst->cUsed; /** @todo Use pDst->cMixed later? */ 1090 1091 AUDMIXBUF_LOG(("%s (%RU32 available) -> %s (%RU32 available)\n", 1092 pSrc->pszName, cSrcAvail, pDst->pszName, cDstAvail)); 1093 #ifdef DEBUG 1094 audioMixBufDbgPrintInternal(pDst, __FUNCTION__); 1095 #endif 1096 1097 if (!cSrcAvail) 1098 return VERR_BUFFER_UNDERFLOW; 1099 1100 if (!cDstAvail) 1066 1101 return VERR_BUFFER_OVERFLOW; 1067 }1068 1069 Assert(pSrc->cUsed >= pDst->cMixed);1070 1071 uint32_t cSrcAvail = RT_MIN(cSrcSamples, pSrc->cUsed - pDst->cMixed);1072 uint32_t offSrcRead = pSrc->offRead;1073 uint32_t cDstMixed = pSrc->cMixed;1074 1075 Assert(pDst->cUsed <= pDst->cSamples);1076 uint32_t cDstAvail = pDst->cSamples - pDst->cUsed;1077 uint32_t offDstWrite = pDst->offWrite;1078 1079 AUDMIXBUF_LOG(("cSrcSamples=%RU32, cSrcAvail=%RU32 -> cDstAvail=%RU32\n", cSrcSamples, cSrcAvail, cDstAvail));1080 1081 if ( !cSrcAvail1082 || !cDstAvail)1083 {1084 if (pcProcessed)1085 *pcProcessed = 0;1086 return VINF_SUCCESS;1087 }1088 1089 #ifdef DEBUG1090 audioMixBufDbgPrintInternal(pDst);1091 #endif1092 1102 1093 1103 uint32_t cSrcToRead = 0; … … 1099 1109 int rc = VINF_SUCCESS; 1100 1110 1101 while ( cSrcAvail 1102 && cDstAvail) 1111 while (cSrcAvail && cDstAvail) 1103 1112 { 1104 1113 cSrcToRead = RT_MIN(cSrcAvail, pSrc->cSamples - offSrcRead); 1105 1114 cDstToWrite = RT_MIN(cDstAvail, pDst->cSamples - offDstWrite); 1106 1115 1107 AUDMIXBUF_LOG(("\tSource: %RU32 samples available, %RU32 @ %RU32 -> reading %RU32\n", cSrcAvail, offSrcRead, pSrc->cSamples, cSrcToRead)); 1108 AUDMIXBUF_LOG(("\tDest : %RU32 samples available, %RU32 @ %RU32 -> writing %RU32\n", cDstAvail, offDstWrite, pDst->cSamples, cDstToWrite)); 1116 AUDMIXBUF_LOG(("\tSource: %RU32 @ %RU32 -> reading %RU32\n", cSrcAvail, offSrcRead, cSrcToRead)); 1117 AUDMIXBUF_LOG(("\tDest : %RU32 @ %RU32 -> writing %RU32\n", cDstAvail, offDstWrite, cDstToWrite)); 1118 1119 if ( !cDstToWrite 1120 || !cSrcToRead) 1121 { 1122 break; 1123 } 1109 1124 1110 1125 cDstWritten = cSrcRead = 0; 1111 1126 1112 if ( cDstToWrite 1113 && cSrcToRead) 1114 { 1115 Assert(offSrcRead < pSrc->cSamples); 1116 Assert(offSrcRead + cSrcToRead <= pSrc->cSamples); 1117 1118 Assert(offDstWrite < pDst->cSamples); 1119 Assert(offDstWrite + cDstToWrite <= pDst->cSamples); 1120 1121 audioMixBufOpAssign(pDst->pSamples + offDstWrite, cDstToWrite, 1122 pSrc->pSamples + offSrcRead, cSrcToRead, 1123 pSrc->pRate, &cDstWritten, &cSrcRead); 1124 } 1127 Assert(offSrcRead < pSrc->cSamples); 1128 Assert(offSrcRead + cSrcToRead <= pSrc->cSamples); 1129 1130 Assert(offDstWrite < pDst->cSamples); 1131 Assert(offDstWrite + cDstToWrite <= pDst->cSamples); 1132 1133 audioMixBufOpAssign(pDst->pSamples + offDstWrite, cDstToWrite, 1134 pSrc->pSamples + offSrcRead, cSrcToRead, 1135 pSrc->pRate, &cDstWritten, &cSrcRead); 1125 1136 1126 1137 cReadTotal += cSrcRead; … … 1133 1144 1134 1145 Assert(cSrcAvail >= cSrcRead); 1135 cSrcAvail -= cSrcRead; 1146 cSrcAvail -= cSrcRead; 1147 1136 1148 Assert(cDstAvail >= cDstWritten); 1137 cDstAvail -= cDstWritten; 1138 1139 AUDMIXBUF_LOG(("\t%RU32 read (%RU32 left), %RU32 written (%RU32 left)\n", cSrcRead, cSrcAvail, cDstWritten, cDstAvail)); 1149 cDstAvail -= cDstWritten; 1150 1151 AUDMIXBUF_LOG(("\t%RU32 read (%RU32 left @ %RU32), %RU32 written (%RU32 left @ %RU32)\n", 1152 cSrcRead, cSrcAvail, offSrcRead, 1153 cDstWritten, cDstAvail, offDstWrite)); 1140 1154 } 1141 1155 1142 1156 pSrc->offRead = offSrcRead; 1143 1157 Assert(pSrc->cUsed >= cReadTotal); 1144 pSrc->cUsed -= cReadTotal;1158 pSrc->cUsed -= RT_MIN(pSrc->cUsed, cReadTotal); 1145 1159 1146 1160 /* Note: Always count in parent samples, as the rate can differ! */ … … 1159 1173 if (pDst->cUsed > pDst->cSamples) 1160 1174 { 1161 LogFunc((" Warning: Destination buffer used %RU32 / %RU32 samples\n", pDst->cUsed, pDst->cSamples));1175 LogFunc(("%s: Warning: Destination buffer used %RU32 / %RU32 samples\n", pDst->pszName, pDst->cUsed, pDst->cSamples)); 1162 1176 pDst->offWrite = 0; 1163 1177 pDst->cUsed = pDst->cSamples; … … 1165 1179 rc = VERR_BUFFER_OVERFLOW; 1166 1180 } 1167 else if (!cSrcToRead && cDstAvail)1168 {1169 LogFunc(("Warning: Source buffer '%s' ran out of data\n", pSrc->pszName));1170 rc = VERR_BUFFER_UNDERFLOW;1171 }1172 else if (cSrcAvail && !cDstAvail)1173 {1174 LogFunc(("Warning: Destination buffer '%s' full (%RU32 source samples left)\n", pDst->pszName, cSrcAvail));1175 rc = VERR_BUFFER_OVERFLOW;1176 }1177 1181 1178 1182 #ifdef DEBUG 1179 s_cSamplesMixedTotal += cWrittenTotal; 1180 audioMixBufDbgPrintInternal(pDst); 1181 #endif 1182 1183 if (pcProcessed) 1184 *pcProcessed = cReadTotal; 1185 1186 AUDMIXBUF_LOG(("cReadTotal=%RU32 (pcProcessed), cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstUsed=%RU32, rc=%Rrc\n", 1183 audioMixBufDbgValidate(pSrc); 1184 audioMixBufDbgValidate(pDst); 1185 1186 Assert(pSrc->cMixed <= pDst->cSamples); 1187 #endif 1188 1189 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1190 uint32_t offRead = pDst->offRead; 1191 1192 uint32_t cLeft = cWrittenTotal; 1193 while (cLeft) 1194 { 1195 uint8_t auBuf[256]; 1196 RT_ZERO(auBuf); 1197 1198 Assert(sizeof(auBuf) >= 4); 1199 Assert(sizeof(auBuf) % 4 == 0); 1200 1201 uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pDst, sizeof(auBuf)), RT_MIN(cLeft, pDst->cSamples - offRead)); 1202 Assert(cToRead <= pDst->cUsed); 1203 1204 PDMAUDMIXBUFCONVOPTS convOpts; 1205 RT_ZERO(convOpts); 1206 convOpts.cSamples = cToRead; 1207 1208 pDst->pfnConvTo(auBuf, pDst->pSamples + offRead, &convOpts); 1209 1210 RTFILE fh; 1211 int rc2 = RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_mixto.pcm", 1212 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1213 if (RT_SUCCESS(rc2)) 1214 { 1215 RTFileWrite(fh, auBuf, AUDIOMIXBUF_S2B(pDst, cToRead), NULL); 1216 RTFileClose(fh); 1217 } 1218 1219 offRead = (offRead + cToRead) % pDst->cSamples; 1220 cLeft -= cToRead; 1221 } 1222 #endif /* AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA */ 1223 1224 #ifdef DEBUG 1225 audioMixBufDbgPrintInternal(pDst, __FUNCTION__); 1226 #endif 1227 1228 if (pcSrcMixed) 1229 *pcSrcMixed = cReadTotal; 1230 1231 AUDMIXBUF_LOG(("cReadTotal=%RU32, cWrittenTotal=%RU32, cSrcMixed=%RU32, cDstUsed=%RU32, rc=%Rrc\n", 1187 1232 cReadTotal, cWrittenTotal, pSrc->cMixed, pDst->cUsed, rc)); 1188 1233 return rc; … … 1190 1235 1191 1236 /** 1192 * Mixes audio samples down to the parent mixing buffer .1237 * Mixes audio samples down to the parent mixing buffer, extended version. 1193 1238 * 1194 1239 * @return IPRT status code. See audioMixBufMixTo() for a more detailed explanation. 1195 * @param pMixBuf Mixing buffer to mix samples down to parent. 1196 * @param cSamples Number of audio samples of specified mixing buffer to to mix 1197 * to its attached parent mixing buffer (if any). 1198 * @param pcProcessed Number of audio samples successfully processed. Optional. 1199 */ 1200 int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, 1201 uint32_t *pcProcessed) 1240 * @param pMixBuf Source mixing buffer to mix to its parent. 1241 * @param cSrcOffset Offset (in samples) of source mixing buffer. 1242 * @param cSrcSamples Number of source audio samples to mix to its parent. 1243 * @param pcSrcMixed Number of source audio samples successfully mixed. Optional. 1244 */ 1245 int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcSamples, uint32_t *pcSrcMixed) 1202 1246 { 1203 1247 AssertMsgReturn(VALID_PTR(pMixBuf->pParent), … … 1205 1249 VERR_INVALID_PARAMETER); 1206 1250 1207 return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, cSamples, pcProcessed); 1251 return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, cSrcOffset, cSrcSamples, pcSrcMixed); 1252 } 1253 1254 /** 1255 * Mixes audio samples down to the parent mixing buffer. 1256 * 1257 * @return IPRT status code. See audioMixBufMixTo() for a more detailed explanation. 1258 * @param pMixBuf Source mixing buffer to mix to its parent. 1259 * @param cSrcSamples Number of source audio samples to mix to its parent. 1260 * @param pcSrcMixed Number of source audio samples successfully mixed. Optional. 1261 */ 1262 int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcSamples, uint32_t *pcSrcMixed) 1263 { 1264 return audioMixBufMixTo(pMixBuf->pParent, pMixBuf, pMixBuf->offRead, cSrcSamples, pcSrcMixed); 1208 1265 } 1209 1266 1210 1267 #ifdef DEBUG 1211 1212 1268 /** 1213 1269 * Prints a single mixing buffer. … … 1216 1272 * @return IPRT status code. 1217 1273 * @param pMixBuf Mixing buffer to print. 1274 * @param pszFunc Function name to log this for. 1218 1275 * @param fIsParent Whether this is a parent buffer or not. 1219 1276 * @param uIdtLvl Indention level to use. 1220 1277 */ 1221 DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, bool fIsParent, uint16_t uIdtLvl) 1222 { 1223 LogFunc(("%*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n", 1224 uIdtLvl * 4, "", fIsParent ? "PARENT" : "CHILD", 1225 pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cMixed, pMixBuf->cUsed, pMixBuf->cSamples)); 1278 DECL_FORCE_INLINE(void) audioMixBufDbgPrintSingle(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, bool fIsParent, uint16_t uIdtLvl) 1279 { 1280 Log(("%s: %*s[%s] %s: offRead=%RU32, offWrite=%RU32, cMixed=%RU32 -> %RU32/%RU32\n", 1281 pszFunc, uIdtLvl * 4, "", fIsParent ? "PARENT" : "CHILD", 1282 pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cMixed, pMixBuf->cUsed, pMixBuf->cSamples)); 1283 } 1284 1285 /** 1286 * Validates a single mixing buffer. 1287 * 1288 * @return @true if the buffer state is valid or @false if not. 1289 * @param pMixBuf Mixing buffer to validate. 1290 */ 1291 DECL_FORCE_INLINE(bool) audioMixBufDbgValidate(PPDMAUDIOMIXBUF pMixBuf) 1292 { 1293 //const uint32_t offReadEnd = (pMixBuf->offRead + pMixBuf->cUsed) % pMixBuf->cSamples; 1294 //const uint32_t offWriteEnd = (pMixBuf->offWrite + (pMixBuf->cSamples - pMixBuf->cUsed)) % pMixBuf->cSamples; 1295 1296 bool fValid = true; 1297 1298 AssertStmt(pMixBuf->offRead <= pMixBuf->cSamples, fValid = false); 1299 AssertStmt(pMixBuf->offWrite <= pMixBuf->cSamples, fValid = false); 1300 AssertStmt(pMixBuf->cUsed <= pMixBuf->cSamples, fValid = false); 1301 1302 if (pMixBuf->offWrite > pMixBuf->offRead) 1303 { 1304 if (pMixBuf->offWrite - pMixBuf->offRead != pMixBuf->cUsed) 1305 fValid = false; 1306 } 1307 else if (pMixBuf->offWrite < pMixBuf->offRead) 1308 { 1309 if (pMixBuf->offWrite + pMixBuf->cSamples - pMixBuf->offRead != pMixBuf->cUsed) 1310 fValid = false; 1311 } 1312 1313 if (!fValid) 1314 { 1315 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__); 1316 AssertFailed(); 1317 } 1318 1319 return fValid; 1226 1320 } 1227 1321 … … 1232 1326 * @return IPRT status code. 1233 1327 * @param pMixBuf Mixing buffer to print. 1328 * @param pszFunc Function name to print the chain for. 1234 1329 * @param uIdtLvl Indention level to use. 1235 1330 * @param pcChildren Pointer to children counter. 1236 1331 */ 1237 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, uint16_t uIdtLvl, size_t *pcChildren) 1332 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainHelper(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl, 1333 size_t *pcChildren) 1238 1334 { 1239 1335 PPDMAUDIOMIXBUF pIter; 1240 1336 RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node) 1241 1337 { 1242 audioMixBufDbgPrintSingle(pIter, false /* ifIsParent */, uIdtLvl + 1);1338 audioMixBufDbgPrintSingle(pIter, pszFunc, false /* ifIsParent */, uIdtLvl + 1); 1243 1339 *pcChildren++; 1244 1340 } 1245 1341 } 1246 1342 1247 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf )1343 DECL_FORCE_INLINE(void) audioMixBufDbgPrintChainInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc) 1248 1344 { 1249 1345 PPDMAUDIOMIXBUF pParent = pMixBuf->pParent; … … 1259 1355 pParent = pMixBuf; 1260 1356 1261 AUDMIXBUF_LOG(("********************************************\n")); 1262 1263 audioMixBufDbgPrintSingle(pParent, true /* fIsParent */, 0 /* uIdtLvl */); 1357 audioMixBufDbgPrintSingle(pParent, pszFunc, true /* fIsParent */, 0 /* uIdtLvl */); 1264 1358 1265 1359 /* Recursively iterate children. */ 1266 1360 size_t cChildren = 0; 1267 audioMixBufDbgPrintChainHelper(pParent, 0 /* uIdtLvl */, &cChildren); 1268 1269 AUDMIXBUF_LOG(("Children: %zu - Total samples mixed: %RU64\n", cChildren, s_cSamplesMixedTotal)); 1270 AUDMIXBUF_LOG(("********************************************\n")); 1361 audioMixBufDbgPrintChainHelper(pParent, pszFunc, 0 /* uIdtLvl */, &cChildren); 1362 1363 Log(("%s: Children: %zu\n", pszFunc, cChildren)); 1271 1364 } 1272 1365 … … 1281 1374 void AudioMixBufDbgPrintChain(PPDMAUDIOMIXBUF pMixBuf) 1282 1375 { 1283 audioMixBufDbgPrintChainInternal(pMixBuf );1284 } 1285 1286 DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf )1376 audioMixBufDbgPrintChainInternal(pMixBuf, __FUNCTION__); 1377 } 1378 1379 DECL_FORCE_INLINE(void) audioMixBufDbgPrintInternal(PPDMAUDIOMIXBUF pMixBuf, const char *pszFunc) 1287 1380 { 1288 1381 PPDMAUDIOMIXBUF pParent = pMixBuf; … … 1290 1383 pParent = pMixBuf->pParent; 1291 1384 1292 LogFunc(("***************************************************************************************\n")); 1293 1294 audioMixBufDbgPrintSingle(pMixBuf, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */); 1385 audioMixBufDbgPrintSingle(pMixBuf, pszFunc, pParent == pMixBuf /* fIsParent */, 0 /* iIdtLevel */); 1295 1386 1296 1387 PPDMAUDIOMIXBUF pIter; 1297 RTListForEach(&p Parent->lstChildren, pIter, PDMAUDIOMIXBUF, Node)1388 RTListForEach(&pMixBuf->lstChildren, pIter, PDMAUDIOMIXBUF, Node) 1298 1389 { 1299 1390 if (pIter == pMixBuf) 1300 1391 continue; 1301 audioMixBufDbgPrintSingle(pIter, false /* fIsParent */, 1 /* iIdtLevel */); 1302 } 1303 1304 LogFunc(("***************************************************************************************\n")); 1392 audioMixBufDbgPrintSingle(pIter, pszFunc, false /* fIsParent */, 1 /* iIdtLevel */); 1393 } 1305 1394 } 1306 1395 … … 1314 1403 void AudioMixBufDbgPrint(PPDMAUDIOMIXBUF pMixBuf) 1315 1404 { 1316 audioMixBufDbgPrintInternal(pMixBuf); 1317 } 1318 1405 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__); 1406 } 1319 1407 #endif /* DEBUG */ 1320 1408 … … 1454 1542 { 1455 1543 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); 1544 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 1456 1545 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1457 /* pcbRead is optional. */ 1458 1459 if (!cbBuf) 1460 { 1461 if (pcRead) 1462 *pcRead = 0; 1463 return VINF_SUCCESS; 1464 } 1465 1466 uint32_t cToRead = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cUsed); 1546 /* pcRead is optional. */ 1547 1548 /* Make sure that we at least have space for a full audio sample. */ 1549 AssertReturn(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), VERR_INVALID_PARAMETER); 1550 1551 uint32_t cToRead = RT_MIN(pMixBuf->cUsed, AUDIOMIXBUF_B2S(pMixBuf, cbBuf)); 1467 1552 1468 1553 AUDMIXBUF_LOG(("%s: cbBuf=%RU32 (%RU32 samples), cToRead=%RU32, fmtSrc=0x%x, fmtDst=0x%x\n", … … 1472 1557 { 1473 1558 #ifdef DEBUG 1474 audioMixBufDbgPrintInternal(pMixBuf );1559 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__); 1475 1560 #endif 1476 1561 if (pcRead) … … 1491 1576 } 1492 1577 1493 PPDMAUDIOSAMPLE pSamplesSrc1 = pMixBuf->pSamples + pMixBuf->offRead; 1494 uint32_t cLenSrc1 = cToRead; 1495 1496 PPDMAUDIOSAMPLE pSamplesSrc2 = NULL; 1497 uint32_t cLenSrc2 = 0; 1498 1499 /* 1500 * Do we need to wrap around to read all requested data, that is, 1501 * starting at the beginning of our circular buffer? This then will 1502 * be the optional second part to do. 1503 */ 1504 if ((pMixBuf->offRead + cToRead) > pMixBuf->cSamples) 1505 { 1506 Assert(pMixBuf->offRead <= pMixBuf->cSamples); 1507 cLenSrc1 = pMixBuf->cSamples - pMixBuf->offRead; 1508 1509 pSamplesSrc2 = pMixBuf->pSamples; 1510 Assert(cToRead >= cLenSrc1); 1511 cLenSrc2 = RT_MIN(cToRead - cLenSrc1, pMixBuf->cSamples); 1512 } 1513 1514 PDMAUDMIXBUFCONVOPTS convOpts; 1515 RT_ZERO(convOpts); 1516 /* Note: No volume handling/conversion done in the conversion-to macros (yet). */ 1517 1518 /* Anything to do at all? */ 1519 int rc = VINF_SUCCESS; 1520 if (cLenSrc1) 1521 { 1522 AssertPtr(pSamplesSrc1); 1523 1524 convOpts.cSamples = cLenSrc1; 1525 1526 AUDMIXBUF_LOG(("P1: offRead=%RU32, cToRead=%RU32\n", pMixBuf->offRead, cLenSrc1)); 1527 pfnConvTo(pvBuf, pSamplesSrc1, &convOpts); 1528 } 1529 1530 /* Second part present? */ 1531 if ( RT_LIKELY(RT_SUCCESS(rc)) 1532 && cLenSrc2) 1533 { 1534 AssertPtr(pSamplesSrc2); 1535 1536 convOpts.cSamples = cLenSrc2; 1537 1538 AUDMIXBUF_LOG(("P2: cToRead=%RU32, offWrite=%RU32 (%zu bytes)\n", cLenSrc2, cLenSrc1, 1539 AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1))); 1540 pfnConvTo((uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenSrc1), pSamplesSrc2, &convOpts); 1541 } 1542 1543 if (RT_SUCCESS(rc)) 1544 { 1578 cToRead = RT_MIN(cToRead, pMixBuf->cSamples - pMixBuf->offRead); 1579 if (cToRead) 1580 { 1581 PDMAUDMIXBUFCONVOPTS convOpts; 1582 RT_ZERO(convOpts); 1583 convOpts.cSamples = cToRead; 1584 1585 AUDMIXBUF_LOG(("cToRead=%RU32\n", cToRead)); 1586 1587 pfnConvTo(pvBuf, pMixBuf->pSamples + pMixBuf->offRead, &convOpts); 1588 1545 1589 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1546 1590 RTFILE fh; 1547 rc= RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_readcirc.pcm",1548 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);1549 if (RT_SUCCESS(rc ))1591 int rc2 = RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_readcirc.pcm", 1592 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1593 if (RT_SUCCESS(rc2)) 1550 1594 { 1551 RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, c LenSrc1 + cLenSrc2), NULL);1595 RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToRead), NULL); 1552 1596 RTFileClose(fh); 1553 1597 } 1554 1598 #endif 1555 1599 pMixBuf->offRead = (pMixBuf->offRead + cToRead) % pMixBuf->cSamples; 1556 Assert( cToRead <= pMixBuf->cUsed);1557 pMixBuf->cUsed -= RT_MIN(cToRead, pMixBuf->cUsed);1558 1559 if (pcRead) 1560 *pcRead = cToRead;1561 }1600 Assert(pMixBuf->cUsed >= cToRead); 1601 pMixBuf->cUsed -= cToRead; 1602 } 1603 1604 if (pcRead) 1605 *pcRead = cToRead; 1562 1606 1563 1607 #ifdef DEBUG 1564 audioMixBufDbgPrintInternal(pMixBuf); 1565 #endif 1566 1567 AUDMIXBUF_LOG(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n", cToRead, AUDIOMIXBUF_S2B(pMixBuf, cToRead), rc)); 1568 return rc; 1608 audioMixBufDbgValidate(pMixBuf); 1609 #endif 1610 1611 AUDMIXBUF_LOG(("cRead=%RU32 (%RU32 bytes)\n", cToRead, AUDIOMIXBUF_S2B(pMixBuf, cToRead))); 1612 return VINF_SUCCESS; 1613 } 1614 1615 /** 1616 * Returns the current read position of a mixing buffer. 1617 * 1618 * @returns IPRT status code. 1619 * @param pMixBuf Mixing buffer to return position for. 1620 */ 1621 uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf) 1622 { 1623 AssertPtrReturn(pMixBuf, 0); 1624 1625 return pMixBuf->offRead; 1569 1626 } 1570 1627 … … 1642 1699 AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName)); 1643 1700 1644 if (pMixBuf->pParent) 1701 if (pMixBuf->pParent) /* IS this a children buffer? */ 1645 1702 { 1646 1703 AUDMIXBUF_LOG(("%s: Unlinking from parent \"%s\"\n", … … 1648 1705 1649 1706 RTListNodeRemove(&pMixBuf->Node); 1707 1708 /* Decrease the paren't children count. */ 1709 Assert(pMixBuf->pParent->cChildren); 1710 pMixBuf->pParent->cChildren--; 1650 1711 1651 1712 /* Make sure to reset the parent mixing buffer each time it gets linked … … 1666 1727 1667 1728 RTListNodeRemove(&pChild->Node); 1729 1730 /* Decrease the children count. */ 1731 Assert(pMixBuf->cChildren); 1732 pMixBuf->cChildren--; 1668 1733 } 1669 1734 1670 1735 Assert(RTListIsEmpty(&pMixBuf->lstChildren)); 1736 Assert(pMixBuf->cChildren == 0); 1671 1737 1672 1738 AudioMixBufReset(pMixBuf); … … 1699 1765 /** 1700 1766 * Writes audio samples at a specific offset. 1767 * 1768 * Note that this operation also modifies the current read and write position 1769 * to \a offSamples + written samples on success. 1701 1770 * 1702 1771 * The audio sample format to be written can be different from the audio format … … 1712 1781 */ 1713 1782 int AudioMixBufWriteAtEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, 1714 uint32_t offSamples, 1715 const void *pvBuf, uint32_t cbBuf, 1783 uint32_t offSamples, const void *pvBuf, uint32_t cbBuf, 1716 1784 uint32_t *pcWritten) 1717 1785 { 1718 1786 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER); 1787 AssertReturn(cbBuf, VERR_INVALID_PARAMETER); 1719 1788 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1720 /* pcWritten is optional. */ 1789 /* pcbWritten is optional. */ 1790 1791 if (offSamples >= pMixBuf->cSamples) 1792 { 1793 if (pcWritten) 1794 *pcWritten = 0; 1795 return VERR_BUFFER_OVERFLOW; 1796 } 1721 1797 1722 1798 /* 1723 1799 * Adjust cToWrite so we don't overflow our buffers. 1724 1800 */ 1725 int rc; 1726 uint32_t cToWrite = AUDIOMIXBUF_B2S(pMixBuf, cbBuf); 1727 if (offSamples <= pMixBuf->cSamples) 1728 { 1729 if (offSamples + cToWrite <= pMixBuf->cSamples) 1730 rc = VINF_SUCCESS; 1731 else 1732 { 1733 rc = VINF_BUFFER_OVERFLOW; 1734 cToWrite = pMixBuf->cSamples - offSamples; 1735 } 1736 } 1737 else 1738 { 1739 rc = VINF_BUFFER_OVERFLOW; 1740 cToWrite = 0; 1741 } 1801 uint32_t cToWrite = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), pMixBuf->cSamples - offSamples); 1742 1802 1743 1803 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA … … 1769 1829 pfnConvFrom = &audioMixBufConvFromSilence; 1770 1830 1831 int rc = VINF_SUCCESS; 1832 1771 1833 uint32_t cWritten; 1772 1834 if ( pfnConvFrom … … 1792 1854 } 1793 1855 1794 #ifdef DEBUG1795 audioMixBufDbgPrintInternal(pMixBuf);1796 #endif1797 1798 1856 AUDMIXBUF_LOG(("%s: offSamples=%RU32, cbBuf=%RU32, cToWrite=%RU32 (%zu bytes), cWritten=%RU32 (%zu bytes), rc=%Rrc\n", 1799 1857 pMixBuf->pszName, offSamples, cbBuf, … … 1801 1859 cWritten, AUDIOMIXBUF_S2B(pMixBuf, cWritten), rc)); 1802 1860 1803 if (RT_SUCCESS(rc) && pcWritten) 1804 *pcWritten = cWritten; 1861 if (RT_SUCCESS(rc)) 1862 { 1863 pMixBuf->offRead = offSamples % pMixBuf->cSamples; 1864 pMixBuf->offWrite = (offSamples + cWritten) % pMixBuf->cSamples; 1865 pMixBuf->cUsed = cWritten; 1866 pMixBuf->cMixed = 0; 1867 1868 #ifdef DEBUG 1869 audioMixBufDbgValidate(pMixBuf); 1870 #endif 1871 if (pcWritten) 1872 *pcWritten = cWritten; 1873 } 1874 else 1875 AUDMIXBUF_LOG(("%s: Failed with %Rrc\n", pMixBuf->pszName, rc)); 1805 1876 1806 1877 return rc; … … 1828 1899 /** 1829 1900 * Writes audio samples of a specific format. 1830 * 1831 * @return IPRT status code, or VERR_BUFFER_OVERFLOW if samples which not have1832 * been processed yet have been overwritten (due to cyclic buffer).1901 * This function might write less data at once than requested. 1902 * 1903 * @return IPRT status code, or VERR_BUFFER_OVERFLOW no space is available for writing anymore. 1833 1904 * @param pMixBuf Pointer to mixing buffer to write to. 1834 1905 * @param enmFmt Audio format supplied in the buffer. … … 1851 1922 } 1852 1923 1853 PPDMAUDIOMIXBUF pParent = pMixBuf->pParent; 1854 1855 AUDMIXBUF_LOG(("%s: enmFmt=0x%x, cbBuf=%RU32 (%RU32 samples)\n", 1856 pMixBuf->pszName, enmFmt, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf))); 1857 1858 if ( pParent 1859 && pParent->cSamples < pMixBuf->cMixed) 1860 { 1861 if (pcWritten) 1862 *pcWritten = 0; 1863 1864 AUDMIXBUF_LOG(("%s: Parent buffer '%s' is full\n", 1865 pMixBuf->pszName, pMixBuf->pParent->pszName)); 1866 1867 return VERR_BUFFER_OVERFLOW; 1868 } 1924 /* Make sure that we at least write a full audio sample. */ 1925 AssertReturn(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), VERR_INVALID_PARAMETER); 1926 1927 Assert(pMixBuf->cSamples); 1928 AssertPtr(pMixBuf->pSamples); 1869 1929 1870 1930 PFNPDMAUDIOMIXBUFCONVFROM pfnConvFrom = NULL; … … 1885 1945 } 1886 1946 1887 uint32_t cToWrite = AUDIOMIXBUF_B2S(pMixBuf, cbBuf); 1888 AssertMsg(cToWrite, ("cToWrite is 0 (cbBuf=%zu)\n", cbBuf)); 1889 1890 PPDMAUDIOSAMPLE pSamplesDst1 = pMixBuf->pSamples + pMixBuf->offWrite; 1891 uint32_t cLenDst1 = cToWrite; 1892 1893 PPDMAUDIOSAMPLE pSamplesDst2 = NULL; 1894 uint32_t cLenDst2 = 0; 1895 1896 uint32_t cOffWrite = pMixBuf->offWrite + cToWrite; 1897 1898 /* 1899 * Do we need to wrap around to write all requested data, that is, 1900 * starting at the beginning of our circular buffer? This then will 1901 * be the optional second part to do. 1902 */ 1903 if (cOffWrite >= pMixBuf->cSamples) 1904 { 1947 int rc = VINF_SUCCESS; 1948 1949 uint32_t cWritten = 0; 1950 1951 uint32_t cFree = pMixBuf->cSamples - pMixBuf->cUsed; 1952 if (cFree) 1953 { 1954 if ((pMixBuf->cSamples - pMixBuf->offWrite) == 0) 1955 pMixBuf->offWrite = 0; 1956 1957 uint32_t cToWrite = RT_MIN(AUDIOMIXBUF_B2S(pMixBuf, cbBuf), RT_MIN(pMixBuf->cSamples - pMixBuf->offWrite, cFree)); 1958 Assert(cToWrite); 1959 1960 PDMAUDMIXBUFCONVOPTS convOpts; 1961 RT_ZERO(convOpts); 1962 1963 convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted; 1964 convOpts.From.Volume.uLeft = pMixBuf->Volume.uLeft; 1965 convOpts.From.Volume.uRight = pMixBuf->Volume.uRight; 1966 1967 convOpts.cSamples = cToWrite; 1968 1969 cWritten = pfnConvFrom(pMixBuf->pSamples + pMixBuf->offWrite, 1970 pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), &convOpts); 1971 Assert(cWritten == cToWrite); 1972 1973 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1974 RTFILE fh; 1975 RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex.pcm", 1976 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1977 RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cToWrite), NULL); 1978 RTFileClose(fh); 1979 #endif 1980 pMixBuf->cUsed += cWritten; 1981 Assert(pMixBuf->cUsed <= pMixBuf->cSamples); 1982 1983 pMixBuf->offWrite = (pMixBuf->offWrite + cWritten) % pMixBuf->cSamples; 1905 1984 Assert(pMixBuf->offWrite <= pMixBuf->cSamples); 1906 cLenDst1 = pMixBuf->cSamples - pMixBuf->offWrite; 1907 1908 pSamplesDst2 = pMixBuf->pSamples; 1909 Assert(cToWrite >= cLenDst1); 1910 cLenDst2 = RT_MIN(cToWrite - cLenDst1, pMixBuf->cSamples); 1911 1912 /* Save new read offset. */ 1913 cOffWrite = cLenDst2; 1914 } 1915 1916 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1917 RTFILE fh; 1918 RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex.pcm", 1919 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 1920 #endif 1921 1922 uint32_t cWrittenTotal = 0; 1923 1924 PDMAUDMIXBUFCONVOPTS convOpts; 1925 convOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted; 1926 convOpts.From.Volume.uLeft = pMixBuf->Volume.uLeft; 1927 convOpts.From.Volume.uRight = pMixBuf->Volume.uRight; 1928 1929 /* Anything to do at all? */ 1930 if (cLenDst1) 1931 { 1932 convOpts.cSamples = cLenDst1; 1933 cWrittenTotal = pfnConvFrom(pSamplesDst1, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), &convOpts); 1934 Assert(cWrittenTotal == cLenDst1); 1935 1936 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1937 RTFileWrite(fh, pvBuf, AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL); 1938 #endif 1939 } 1940 1941 /* Second part present? */ 1942 if (cLenDst2) 1943 { 1944 AssertPtr(pSamplesDst2); 1945 1946 convOpts.cSamples = cLenDst2; 1947 cWrittenTotal += pfnConvFrom(pSamplesDst2, 1948 (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1949 cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1950 &convOpts); 1951 Assert(cWrittenTotal == cLenDst1 + cLenDst2); 1952 1953 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1954 RTFileWrite(fh, (uint8_t *)pvBuf + AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), 1955 cbBuf - AUDIOMIXBUF_S2B(pMixBuf, cLenDst1), NULL); 1956 #endif 1957 } 1958 1959 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA 1960 RTFileClose(fh); 1961 #endif 1962 1963 pMixBuf->offWrite = (pMixBuf->offWrite + cWrittenTotal) % pMixBuf->cSamples; 1964 pMixBuf->cUsed += cWrittenTotal; 1965 1966 int rc = VINF_SUCCESS; 1967 1968 if (pMixBuf->cUsed > pMixBuf->cSamples) 1969 { 1970 AUDMIXBUF_LOG(("Warning: %RU32 unprocessed samples overwritten\n", pMixBuf->cUsed - pMixBuf->cSamples)); 1971 pMixBuf->cUsed = pMixBuf->cSamples; 1972 1985 } 1986 else 1973 1987 rc = VERR_BUFFER_OVERFLOW; 1974 } 1988 1989 #ifdef DEBUG 1990 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__); 1991 audioMixBufDbgValidate(pMixBuf); 1992 #endif 1975 1993 1976 1994 if (pcWritten) 1977 *pcWritten = cWrittenTotal; 1978 1979 #ifdef DEBUG 1980 audioMixBufDbgPrintInternal(pMixBuf); 1981 #endif 1982 1983 AUDMIXBUF_LOG(("%s: offWrite=%RU32, cLenDst1=%RU32, cLenDst2=%RU32, cTotal=%RU32 (%zu bytes), rc=%Rrc\n", 1984 pMixBuf->pszName, pMixBuf->offWrite, cLenDst1, cLenDst2, cLenDst1 + cLenDst2, 1985 AUDIOMIXBUF_S2B(pMixBuf, cLenDst1 + cLenDst2), rc)); 1995 *pcWritten = cWritten; 1996 1997 AUDMIXBUF_LOG(("%s: enmFmt=0x%x, cbBuf=%RU32 (%RU32 samples), cWritten=%RU32, rc=%Rrc\n", 1998 pMixBuf->pszName, enmFmt, cbBuf, AUDIOMIXBUF_B2S(pMixBuf, cbBuf), cWritten, rc)); 1986 1999 return rc; 1987 2000 } 1988 2001 2002 /** 2003 * Returns the current write position of a mixing buffer. 2004 * 2005 * @returns IPRT status code. 2006 * @param pMixBuf Mixing buffer to return position for. 2007 */ 2008 uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf) 2009 { 2010 AssertPtrReturn(pMixBuf, 0); 2011 2012 return pMixBuf->offWrite; 2013 } 2014 -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
r65739 r67365 5 5 6 6 /* 7 * Copyright (C) 2014-201 6Oracle Corporation7 * Copyright (C) 2014-2017 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 59 59 int AudioMixBufLinkTo(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOMIXBUF pParent); 60 60 uint32_t AudioMixBufLive(PPDMAUDIOMIXBUF pMixBuf); 61 int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamples, uint32_t *pcProcessed); 61 int AudioMixBufMixToParent(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcSamples, uint32_t *pcSrcMixed); 62 int AudioMixBufMixToParentEx(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSrcOffset, uint32_t cSrcSamples, uint32_t *pcSrcMixed); 62 63 int AudioMixBufPeek(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead, PPDMAUDIOSAMPLE paSampleBuf, uint32_t cSampleBuf, uint32_t *pcSamplesRead); 63 64 int AudioMixBufPeekMutable(PPDMAUDIOMIXBUF pMixBuf, uint32_t cSamplesToRead, PPDMAUDIOSAMPLE *ppvSamples, uint32_t *pcSamplesRead); … … 67 68 int AudioMixBufReadCirc(PPDMAUDIOMIXBUF pMixBuf, void *pvBuf, uint32_t cbBuf, uint32_t *pcRead); 68 69 int AudioMixBufReadCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, void *pvBuf, uint32_t cbBuf, uint32_t *pcRead); 70 uint32_t AudioMixBufReadPos(PPDMAUDIOMIXBUF pMixBuf); 69 71 void AudioMixBufReset(PPDMAUDIOMIXBUF pMixBuf); 70 72 void AudioMixBufSetVolume(PPDMAUDIOMIXBUF pMixBuf, PPDMAUDIOVOLUME pVol); … … 76 78 int AudioMixBufWriteCirc(PPDMAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten); 77 79 int AudioMixBufWriteCircEx(PPDMAUDIOMIXBUF pMixBuf, PDMAUDIOMIXBUFFMT enmFmt, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten); 80 uint32_t AudioMixBufWritePos(PPDMAUDIOMIXBUF pMixBuf); 78 81 79 82 #ifdef DEBUG
Note:
See TracChangeset
for help on using the changeset viewer.