Changeset 88008 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Mar 8, 2021 12:31:30 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143136
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp
r88007 r88008 113 113 case 32: return PDMAUDIOFMT_U32; 114 114 default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID); 115 }116 }117 }118 119 /**120 * Clears a sample buffer by the given amount of audio frames with silence (according to the format121 * given by the PCM properties).122 *123 * @param pPCMProps PCM properties to use for the buffer to clear.124 * @param pvBuf Buffer to clear.125 * @param cbBuf Size (in bytes) of the buffer.126 * @param cFrames Number of audio frames to clear in the buffer.127 */128 void DrvAudioHlpClearBuf(PCPDMAUDIOPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cFrames)129 {130 /*131 * Validate input132 */133 AssertPtrReturnVoid(pPCMProps);134 Assert(pPCMProps->cbSample);135 if (!cbBuf || !cFrames)136 return;137 AssertPtrReturnVoid(pvBuf);138 139 Assert(pPCMProps->fSwapEndian == false); /** @todo Swapping Endianness is not supported yet. */140 141 /*142 * Decide how much needs clearing.143 */144 size_t cbToClear = DrvAudioHlpFramesToBytes(pPCMProps, cFrames);145 AssertStmt(cbToClear <= cbBuf, cbToClear = cbBuf);146 147 Log2Func(("pPCMProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cBytes=%RU8\n",148 pPCMProps, pvBuf, cFrames, pPCMProps->fSigned, pPCMProps->cbSample));149 150 /*151 * Do the job.152 */153 if (pPCMProps->fSigned)154 RT_BZERO(pvBuf, cbToClear);155 else /* Unsigned formats. */156 {157 switch (pPCMProps->cbSample)158 {159 case 1: /* 8 bit */160 memset(pvBuf, 0x80, cbToClear);161 break;162 163 case 2: /* 16 bit */164 {165 uint16_t *pu16Dst = (uint16_t *)pvBuf;166 size_t cLeft = cbToClear / sizeof(uint16_t);167 while (cLeft-- > 0)168 *pu16Dst++ = 0x80;169 break;170 }171 172 /** @todo Add 24 bit? */173 174 case 4: /* 32 bit */175 ASMMemFill32(pvBuf, cbToClear & ~(size_t)3, 0x80);176 break;177 178 default:179 AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pPCMProps->cbSample));180 115 } 181 116 } … … 800 735 AssertMsgFailed(("Invalid audio format '%s'\n", pszFmt)); 801 736 return PDMAUDIOFMT_INVALID; 737 } 738 739 /** 740 * Initializes a stream configuration with its default values. 741 * 742 * @param pCfg Stream configuration to initialize. 743 */ 744 void DrvAudioHlpStreamCfgInit(PPDMAUDIOSTREAMCFG pCfg) 745 { 746 AssertPtrReturnVoid(pCfg); 747 748 RT_ZERO(*pCfg); 749 750 pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */ 751 } 752 753 /** 754 * Checks whether a given stream configuration is valid or not. 755 * 756 * Returns @c true if configuration is valid, @c false if not. 757 * @param pCfg Stream configuration to check. 758 */ 759 bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg) 760 { 761 AssertPtrReturn(pCfg, false); 762 763 bool fValid = ( pCfg->enmDir == PDMAUDIODIR_IN 764 || pCfg->enmDir == PDMAUDIODIR_OUT); 765 766 fValid &= ( pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED 767 || pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 768 769 if (fValid) 770 fValid = DrvAudioHlpPCMPropsAreValid(&pCfg->Props); 771 772 return fValid; 773 } 774 775 /** 776 * Frees an allocated audio stream configuration. 777 * 778 * @param pCfg Audio stream configuration to free. 779 */ 780 void DrvAudioHlpStreamCfgFree(PPDMAUDIOSTREAMCFG pCfg) 781 { 782 if (pCfg) 783 { 784 RTMemFree(pCfg); 785 pCfg = NULL; 786 } 787 } 788 789 /** 790 * Copies a source stream configuration to a destination stream configuration. 791 * 792 * @returns IPRT status code. 793 * @param pDstCfg Destination stream configuration to copy source to. 794 * @param pSrcCfg Source stream configuration to copy to destination. 795 */ 796 int DrvAudioHlpStreamCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg) 797 { 798 AssertPtrReturn(pDstCfg, VERR_INVALID_POINTER); 799 AssertPtrReturn(pSrcCfg, VERR_INVALID_POINTER); 800 801 #ifdef VBOX_STRICT 802 if (!DrvAudioHlpStreamCfgIsValid(pSrcCfg)) 803 { 804 AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pSrcCfg->szName, pSrcCfg)); 805 return VERR_INVALID_PARAMETER; 806 } 807 #endif 808 809 memcpy(pDstCfg, pSrcCfg, sizeof(PDMAUDIOSTREAMCFG)); 810 811 return VINF_SUCCESS; 812 } 813 814 /** 815 * Duplicates an audio stream configuration. 816 * Must be free'd with DrvAudioHlpStreamCfgFree(). 817 * 818 * @return Duplicates audio stream configuration on success, or NULL on failure. 819 * @param pCfg Audio stream configuration to duplicate. 820 */ 821 PPDMAUDIOSTREAMCFG DrvAudioHlpStreamCfgDup(PCPDMAUDIOSTREAMCFG pCfg) 822 { 823 AssertPtrReturn(pCfg, NULL); 824 825 #ifdef VBOX_STRICT 826 if (!DrvAudioHlpStreamCfgIsValid(pCfg)) 827 { 828 AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pCfg->szName, pCfg)); 829 return NULL; 830 } 831 #endif 832 833 PPDMAUDIOSTREAMCFG pDst = (PPDMAUDIOSTREAMCFG)RTMemAllocZ(sizeof(PDMAUDIOSTREAMCFG)); 834 if (!pDst) 835 return NULL; 836 837 int rc2 = DrvAudioHlpStreamCfgCopy(pDst, pCfg); 838 if (RT_FAILURE(rc2)) 839 { 840 DrvAudioHlpStreamCfgFree(pDst); 841 pDst = NULL; 842 } 843 844 AssertPtr(pDst); 845 return pDst; 846 } 847 848 /** 849 * Prints an audio stream configuration to the debug log. 850 * 851 * @param pCfg Stream configuration to log. 852 */ 853 void DrvAudioHlpStreamCfgPrint(PCPDMAUDIOSTREAMCFG pCfg) 854 { 855 if (!pCfg) 856 return; 857 858 LogFunc(("szName=%s, enmDir=%RU32 (uHz=%RU32, cBits=%RU8%s, cChannels=%RU8)\n", 859 pCfg->szName, pCfg->enmDir, 860 pCfg->Props.uHz, pCfg->Props.cbSample * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannels)); 861 } 862 863 /** 864 * Converts a stream command to a string. 865 * 866 * @returns Stringified stream command, or "Unknown", if not found. 867 * @param enmCmd Stream command to convert. 868 */ 869 const char *DrvAudioHlpStreamCmdToStr(PDMAUDIOSTREAMCMD enmCmd) 870 { 871 switch (enmCmd) 872 { 873 case PDMAUDIOSTREAMCMD_INVALID: return "Invalid"; 874 case PDMAUDIOSTREAMCMD_UNKNOWN: return "Unknown"; 875 case PDMAUDIOSTREAMCMD_ENABLE: return "Enable"; 876 case PDMAUDIOSTREAMCMD_DISABLE: return "Disable"; 877 case PDMAUDIOSTREAMCMD_PAUSE: return "Pause"; 878 case PDMAUDIOSTREAMCMD_RESUME: return "Resume"; 879 case PDMAUDIOSTREAMCMD_DRAIN: return "Drain"; 880 case PDMAUDIOSTREAMCMD_DROP: return "Drop"; 881 case PDMAUDIOSTREAMCMD_32BIT_HACK: 882 break; 883 } 884 AssertMsgFailed(("Invalid stream command %d\n", enmCmd)); 885 return "Unknown"; 886 } 887 888 /** 889 * Returns @c true if the given stream status indicates a can-be-read-from stream, 890 * @c false if not. 891 * 892 * @returns @c true if ready to be read from, @c if not. 893 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX. 894 */ 895 bool DrvAudioHlpStreamStatusCanRead(PDMAUDIOSTREAMSTS fStatus) 896 { 897 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); 898 899 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED 900 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED 901 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED) 902 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT); 903 } 904 905 /** 906 * Returns @c true if the given stream status indicates a can-be-written-to stream, 907 * @c false if not. 908 * 909 * @returns @c true if ready to be written to, @c if not. 910 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX. 911 */ 912 bool DrvAudioHlpStreamStatusCanWrite(PDMAUDIOSTREAMSTS fStatus) 913 { 914 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); 915 916 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED 917 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED 918 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED) 919 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE) 920 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT); 921 } 922 923 /** 924 * Returns @c true if the given stream status indicates a ready-to-operate stream, 925 * @c false if not. 926 * 927 * @returns @c true if ready to operate, @c if not. 928 * @param fStatus Stream status to evaluate. 929 */ 930 bool DrvAudioHlpStreamStatusIsReady(PDMAUDIOSTREAMSTS fStatus) 931 { 932 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); 933 934 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED 935 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED 936 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT); 937 } 938 939 /** 940 * Calculates the audio bit rate of the given bits per sample, the Hz and the number 941 * of audio channels. 942 * 943 * Divide the result by 8 to get the byte rate. 944 * 945 * @returns Bitrate. 946 * @param cBits Number of bits per sample. 947 * @param uHz Hz (Hertz) rate. 948 * @param cChannels Number of audio channels. 949 */ 950 uint32_t DrvAudioHlpCalcBitrate(uint8_t cBits, uint32_t uHz, uint8_t cChannels) 951 { 952 return cBits * uHz * cChannels; 953 } 954 955 956 /********************************************************************************************************************************* 957 * PCM Property Helpers * 958 *********************************************************************************************************************************/ 959 960 /** 961 * Gets the bitrate. 962 * 963 * Divide the result by 8 to get the byte rate. 964 * 965 * @returns Bit rate. 966 * @param pProps PCM properties to calculate bitrate for. 967 */ 968 uint32_t DrvAudioHlpGetBitrate(PCPDMAUDIOPCMPROPS pProps) 969 { 970 return DrvAudioHlpCalcBitrate(pProps->cbSample * 8, pProps->uHz, pProps->cChannels); 971 } 972 973 /** 974 * Rounds down the given byte amount to the nearest frame boundrary. 975 * 976 * @returns Rounded byte amount. 977 * @param pProps PCM properties to use. 978 * @param cb The size (in bytes) to round. 979 */ 980 uint32_t DrvAudioHlpFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 981 { 982 AssertPtrReturn(pProps, 0); 983 return PDMAUDIOPCMPROPS_F2B(pProps, PDMAUDIOPCMPROPS_B2F(pProps, cb)); 984 } 985 986 /** 987 * Checks if the given size is aligned on a frame boundrary. 988 * 989 * @returns @c true if properly aligned, @c false if not. 990 * @param pProps PCM properties to use. 991 * @param cb The size (in bytes) to check. 992 */ 993 bool DrvAudioHlpIsBytesAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 994 { 995 AssertPtrReturn(pProps, false); 996 uint32_t const cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 997 AssertReturn(cbFrame, false); 998 return cb % cbFrame == 0; 999 } 1000 1001 /** 1002 * Returns the bytes per second for given PCM properties. 1003 * 1004 * @returns Bytes per second. 1005 * @param pProps PCM properties to retrieve size for. 1006 */ 1007 DECLINLINE(uint64_t) drvAudioHlpBytesPerSec(PCPDMAUDIOPCMPROPS pProps) 1008 { 1009 return PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */) * pProps->uHz; 1010 } 1011 1012 /** 1013 * Converts bytes to frames (rounding down of course). 1014 * 1015 * @returns Number of frames. 1016 * @param pProps PCM properties to use. 1017 * @param cb The number of bytes to convert. 1018 */ 1019 uint32_t DrvAudioHlpBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1020 { 1021 AssertPtrReturn(pProps, 0); 1022 return PDMAUDIOPCMPROPS_B2F(pProps, cb); 1023 } 1024 1025 /** 1026 * Converts bytes to milliseconds. 1027 * 1028 * @return Number milliseconds @a cb takes to play or record. 1029 * @param pProps PCM properties to use. 1030 * @param cb The number of bytes to convert. 1031 * 1032 * @note Rounds up the result. 1033 */ 1034 uint64_t DrvAudioHlpBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1035 { 1036 AssertPtrReturn(pProps, 0); 1037 1038 /* Check parameters to prevent division by chainsaw: */ 1039 uint32_t const uHz = pProps->uHz; 1040 if (uHz) 1041 { 1042 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1043 if (cbFrame) 1044 { 1045 /* Round cb up to closest frame size: */ 1046 cb = (cb + cbFrame - 1) / cbFrame; 1047 1048 /* Convert to milliseconds. */ 1049 return (cb * (uint64_t)RT_MS_1SEC + uHz - 1) / uHz; 1050 } 1051 } 1052 return 0; 1053 } 1054 1055 /** 1056 * Converts bytes to microseconds. 1057 * 1058 * @return Number microseconds @a cb takes to play or record. 1059 * @param pProps PCM properties to use. 1060 * @param cb The number of bytes to convert. 1061 * 1062 * @note Rounds up the result. 1063 */ 1064 uint64_t DrvAudioHlpBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1065 { 1066 AssertPtrReturn(pProps, 0); 1067 1068 /* Check parameters to prevent division by chainsaw: */ 1069 uint32_t const uHz = pProps->uHz; 1070 if (uHz) 1071 { 1072 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1073 if (cbFrame) 1074 { 1075 /* Round cb up to closest frame size: */ 1076 cb = (cb + cbFrame - 1) / cbFrame; 1077 1078 /* Convert to microseconds. */ 1079 return (cb * (uint64_t)RT_US_1SEC + uHz - 1) / uHz; 1080 } 1081 } 1082 return 0; 1083 } 1084 1085 /** 1086 * Converts bytes to nanoseconds. 1087 * 1088 * @return Number nanoseconds @a cb takes to play or record. 1089 * @param pProps PCM properties to use. 1090 * @param cb The number of bytes to convert. 1091 * 1092 * @note Rounds up the result. 1093 */ 1094 uint64_t DrvAudioHlpBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1095 { 1096 AssertPtrReturn(pProps, 0); 1097 1098 /* Check parameters to prevent division by chainsaw: */ 1099 uint32_t const uHz = pProps->uHz; 1100 if (uHz) 1101 { 1102 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1103 if (cbFrame) 1104 { 1105 /* Round cb up to closest frame size: */ 1106 cb = (cb + cbFrame - 1) / cbFrame; 1107 1108 /* Convert to nanoseconds. */ 1109 return (cb * (uint64_t)RT_NS_1SEC + uHz - 1) / uHz; 1110 } 1111 } 1112 return 0; 1113 } 1114 1115 /** 1116 * Converts frames to bytes. 1117 * 1118 * @return Number of bytes. 1119 * @param pProps The PCM properties to use. 1120 * @param cFrames Number of audio frames to convert. 1121 */ 1122 uint32_t DrvAudioHlpFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1123 { 1124 AssertPtrReturn(pProps, 0); 1125 return PDMAUDIOPCMPROPS_F2B(pProps, cFrames); 1126 } 1127 1128 /** 1129 * Converts frames to milliseconds. 1130 * 1131 * @returns milliseconds. 1132 * @param pProps The PCM properties to use. 1133 * @param cFrames Number of audio frames to convert. 1134 * @note No rounding here, result is floored. 1135 */ 1136 uint64_t DrvAudioHlpFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1137 { 1138 AssertPtrReturn(pProps, 0); 1139 1140 /* Check input to prevent division by chainsaw: */ 1141 uint32_t const uHz = pProps->uHz; 1142 if (uHz) 1143 return ASMMultU32ByU32DivByU32(cFrames, RT_MS_1SEC, uHz); 1144 return 0; 1145 } 1146 1147 /** 1148 * Converts frames to nanoseconds. 1149 * 1150 * @returns Nanoseconds. 1151 * @param pProps The PCM properties to use. 1152 * @param cFrames Number of audio frames to convert. 1153 * @note No rounding here, result is floored. 1154 */ 1155 uint64_t DrvAudioHlpFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1156 { 1157 AssertPtrReturn(pProps, 0); 1158 1159 /* Check input to prevent division by chainsaw: */ 1160 uint32_t const uHz = pProps->uHz; 1161 if (uHz) 1162 return ASMMultU32ByU32DivByU32(cFrames, RT_NS_1SEC, uHz); 1163 return 0; 1164 } 1165 1166 /** 1167 * Converts milliseconds to frames. 1168 * 1169 * @returns Number of frames 1170 * @param pProps The PCM properties to use. 1171 * @param cMs The number of milliseconds to convert. 1172 * 1173 * @note The result is rounded rather than floored (hysterical raisins). 1174 */ 1175 uint32_t DrvAudioHlpMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs) 1176 { 1177 AssertPtrReturn(pProps, 0); 1178 1179 uint32_t const uHz = pProps->uHz; 1180 uint32_t cFrames; 1181 if (cMs < RT_MS_1SEC) 1182 cFrames = 0; 1183 else 1184 { 1185 cFrames = cMs / RT_MS_1SEC * uHz; 1186 cMs %= RT_MS_1SEC; 1187 } 1188 cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cMs) + RT_MS_1SEC - 1) / RT_MS_1SEC; 1189 return cFrames; 1190 } 1191 1192 /** 1193 * Converts milliseconds to bytes. 1194 * 1195 * @returns Number of bytes (frame aligned). 1196 * @param pProps The PCM properties to use. 1197 * @param cMs The number of milliseconds to convert. 1198 * 1199 * @note The result is rounded rather than floored (hysterical raisins). 1200 */ 1201 uint32_t DrvAudioHlpMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs) 1202 { 1203 return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpMilliToFrames(pProps, cMs)); 1204 } 1205 1206 /** 1207 * Converts nanoseconds to frames. 1208 * 1209 * @returns Number of frames 1210 * @param pProps The PCM properties to use. 1211 * @param cNs The number of nanoseconds to convert. 1212 * 1213 * @note The result is rounded rather than floored (hysterical raisins). 1214 */ 1215 uint32_t DrvAudioHlpNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs) 1216 { 1217 AssertPtrReturn(pProps, 0); 1218 1219 uint32_t const uHz = pProps->uHz; 1220 uint32_t cFrames; 1221 if (cNs < RT_NS_1SEC) 1222 cFrames = 0; 1223 else 1224 { 1225 cFrames = cNs / RT_NS_1SEC * uHz; 1226 cNs %= RT_NS_1SEC; 1227 } 1228 cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cNs) + RT_NS_1SEC - 1) / RT_NS_1SEC; 1229 return cFrames; 1230 } 1231 1232 /** 1233 * Converts nanoseconds to bytes. 1234 * 1235 * @returns Number of bytes (frame aligned). 1236 * @param pProps The PCM properties to use. 1237 * @param cNs The number of nanoseconds to convert. 1238 * 1239 * @note The result is rounded rather than floored (hysterical raisins). 1240 */ 1241 uint32_t DrvAudioHlpNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs) 1242 { 1243 return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpNanoToFrames(pProps, cNs)); 1244 } 1245 1246 /** 1247 * Clears a sample buffer by the given amount of audio frames with silence (according to the format 1248 * given by the PCM properties). 1249 * 1250 * @param pPCMProps PCM properties to use for the buffer to clear. 1251 * @param pvBuf Buffer to clear. 1252 * @param cbBuf Size (in bytes) of the buffer. 1253 * @param cFrames Number of audio frames to clear in the buffer. 1254 */ 1255 void DrvAudioHlpClearBuf(PCPDMAUDIOPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cFrames) 1256 { 1257 /* 1258 * Validate input 1259 */ 1260 AssertPtrReturnVoid(pPCMProps); 1261 Assert(pPCMProps->cbSample); 1262 if (!cbBuf || !cFrames) 1263 return; 1264 AssertPtrReturnVoid(pvBuf); 1265 1266 Assert(pPCMProps->fSwapEndian == false); /** @todo Swapping Endianness is not supported yet. */ 1267 1268 /* 1269 * Decide how much needs clearing. 1270 */ 1271 size_t cbToClear = DrvAudioHlpFramesToBytes(pPCMProps, cFrames); 1272 AssertStmt(cbToClear <= cbBuf, cbToClear = cbBuf); 1273 1274 Log2Func(("pPCMProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cBytes=%RU8\n", 1275 pPCMProps, pvBuf, cFrames, pPCMProps->fSigned, pPCMProps->cbSample)); 1276 1277 /* 1278 * Do the job. 1279 */ 1280 if (pPCMProps->fSigned) 1281 RT_BZERO(pvBuf, cbToClear); 1282 else /* Unsigned formats. */ 1283 { 1284 switch (pPCMProps->cbSample) 1285 { 1286 case 1: /* 8 bit */ 1287 memset(pvBuf, 0x80, cbToClear); 1288 break; 1289 1290 case 2: /* 16 bit */ 1291 { 1292 uint16_t *pu16Dst = (uint16_t *)pvBuf; 1293 size_t cLeft = cbToClear / sizeof(uint16_t); 1294 while (cLeft-- > 0) 1295 *pu16Dst++ = 0x80; 1296 break; 1297 } 1298 1299 /** @todo Add 24 bit? */ 1300 1301 case 4: /* 32 bit */ 1302 ASMMemFill32(pvBuf, cbToClear & ~(size_t)3, 0x80); 1303 break; 1304 1305 default: 1306 AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pPCMProps->cbSample)); 1307 } 1308 } 802 1309 } 803 1310 … … 917 1424 * @param pProps PCM properties to convert. 918 1425 * @param pCfg Stream configuration to store result into. 1426 * @todo r=bird: Rename to DrvAudioHlpStreamCfgInitFromPCMProps. 919 1427 */ 920 1428 int DrvAudioHlpPCMPropsToStreamCfg(PCPDMAUDIOPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg) … … 929 1437 } 930 1438 931 /** 932 * Initializes a stream configuration with its default values. 933 * 934 * @param pCfg Stream configuration to initialize. 935 */ 936 void DrvAudioHlpStreamCfgInit(PPDMAUDIOSTREAMCFG pCfg) 937 { 938 AssertPtrReturnVoid(pCfg); 939 940 RT_ZERO(*pCfg); 941 942 pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */ 943 } 944 945 /** 946 * Checks whether a given stream configuration is valid or not. 947 * 948 * Returns @c true if configuration is valid, @c false if not. 949 * @param pCfg Stream configuration to check. 950 */ 951 bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg) 952 { 953 AssertPtrReturn(pCfg, false); 954 955 bool fValid = ( pCfg->enmDir == PDMAUDIODIR_IN 956 || pCfg->enmDir == PDMAUDIODIR_OUT); 957 958 fValid &= ( pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED 959 || pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 960 961 if (fValid) 962 fValid = DrvAudioHlpPCMPropsAreValid(&pCfg->Props); 963 964 return fValid; 965 } 966 967 /** 968 * Frees an allocated audio stream configuration. 969 * 970 * @param pCfg Audio stream configuration to free. 971 */ 972 void DrvAudioHlpStreamCfgFree(PPDMAUDIOSTREAMCFG pCfg) 973 { 974 if (pCfg) 975 { 976 RTMemFree(pCfg); 977 pCfg = NULL; 978 } 979 } 980 981 /** 982 * Copies a source stream configuration to a destination stream configuration. 983 * 984 * @returns IPRT status code. 985 * @param pDstCfg Destination stream configuration to copy source to. 986 * @param pSrcCfg Source stream configuration to copy to destination. 987 */ 988 int DrvAudioHlpStreamCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg) 989 { 990 AssertPtrReturn(pDstCfg, VERR_INVALID_POINTER); 991 AssertPtrReturn(pSrcCfg, VERR_INVALID_POINTER); 992 993 #ifdef VBOX_STRICT 994 if (!DrvAudioHlpStreamCfgIsValid(pSrcCfg)) 995 { 996 AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pSrcCfg->szName, pSrcCfg)); 997 return VERR_INVALID_PARAMETER; 998 } 999 #endif 1000 1001 memcpy(pDstCfg, pSrcCfg, sizeof(PDMAUDIOSTREAMCFG)); 1002 1003 return VINF_SUCCESS; 1004 } 1005 1006 /** 1007 * Duplicates an audio stream configuration. 1008 * Must be free'd with DrvAudioHlpStreamCfgFree(). 1009 * 1010 * @return Duplicates audio stream configuration on success, or NULL on failure. 1011 * @param pCfg Audio stream configuration to duplicate. 1012 */ 1013 PPDMAUDIOSTREAMCFG DrvAudioHlpStreamCfgDup(PCPDMAUDIOSTREAMCFG pCfg) 1014 { 1015 AssertPtrReturn(pCfg, NULL); 1016 1017 #ifdef VBOX_STRICT 1018 if (!DrvAudioHlpStreamCfgIsValid(pCfg)) 1019 { 1020 AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pCfg->szName, pCfg)); 1021 return NULL; 1022 } 1023 #endif 1024 1025 PPDMAUDIOSTREAMCFG pDst = (PPDMAUDIOSTREAMCFG)RTMemAllocZ(sizeof(PDMAUDIOSTREAMCFG)); 1026 if (!pDst) 1027 return NULL; 1028 1029 int rc2 = DrvAudioHlpStreamCfgCopy(pDst, pCfg); 1030 if (RT_FAILURE(rc2)) 1031 { 1032 DrvAudioHlpStreamCfgFree(pDst); 1033 pDst = NULL; 1034 } 1035 1036 AssertPtr(pDst); 1037 return pDst; 1038 } 1039 1040 /** 1041 * Prints an audio stream configuration to the debug log. 1042 * 1043 * @param pCfg Stream configuration to log. 1044 */ 1045 void DrvAudioHlpStreamCfgPrint(PCPDMAUDIOSTREAMCFG pCfg) 1046 { 1047 if (!pCfg) 1048 return; 1049 1050 LogFunc(("szName=%s, enmDir=%RU32 (uHz=%RU32, cBits=%RU8%s, cChannels=%RU8)\n", 1051 pCfg->szName, pCfg->enmDir, 1052 pCfg->Props.uHz, pCfg->Props.cbSample * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannels)); 1053 } 1054 1055 /** 1056 * Converts a stream command to a string. 1057 * 1058 * @returns Stringified stream command, or "Unknown", if not found. 1059 * @param enmCmd Stream command to convert. 1060 */ 1061 const char *DrvAudioHlpStreamCmdToStr(PDMAUDIOSTREAMCMD enmCmd) 1062 { 1063 switch (enmCmd) 1064 { 1065 case PDMAUDIOSTREAMCMD_INVALID: return "Invalid"; 1066 case PDMAUDIOSTREAMCMD_UNKNOWN: return "Unknown"; 1067 case PDMAUDIOSTREAMCMD_ENABLE: return "Enable"; 1068 case PDMAUDIOSTREAMCMD_DISABLE: return "Disable"; 1069 case PDMAUDIOSTREAMCMD_PAUSE: return "Pause"; 1070 case PDMAUDIOSTREAMCMD_RESUME: return "Resume"; 1071 case PDMAUDIOSTREAMCMD_DRAIN: return "Drain"; 1072 case PDMAUDIOSTREAMCMD_DROP: return "Drop"; 1073 case PDMAUDIOSTREAMCMD_32BIT_HACK: 1074 break; 1075 } 1076 AssertMsgFailed(("Invalid stream command %d\n", enmCmd)); 1077 return "Unknown"; 1078 } 1079 1080 /** 1081 * Returns @c true if the given stream status indicates a can-be-read-from stream, 1082 * @c false if not. 1083 * 1084 * @returns @c true if ready to be read from, @c if not. 1085 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX. 1086 */ 1087 bool DrvAudioHlpStreamStatusCanRead(PDMAUDIOSTREAMSTS fStatus) 1088 { 1089 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); 1090 1091 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED 1092 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED 1093 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED) 1094 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT); 1095 } 1096 1097 /** 1098 * Returns @c true if the given stream status indicates a can-be-written-to stream, 1099 * @c false if not. 1100 * 1101 * @returns @c true if ready to be written to, @c if not. 1102 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX. 1103 */ 1104 bool DrvAudioHlpStreamStatusCanWrite(PDMAUDIOSTREAMSTS fStatus) 1105 { 1106 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); 1107 1108 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED 1109 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED 1110 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED) 1111 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE) 1112 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT); 1113 } 1114 1115 /** 1116 * Returns @c true if the given stream status indicates a ready-to-operate stream, 1117 * @c false if not. 1118 * 1119 * @returns @c true if ready to operate, @c if not. 1120 * @param fStatus Stream status to evaluate. 1121 */ 1122 bool DrvAudioHlpStreamStatusIsReady(PDMAUDIOSTREAMSTS fStatus) 1123 { 1124 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); 1125 1126 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED 1127 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED 1128 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT); 1129 } 1130 1131 /** 1132 * Calculates the audio bit rate of the given bits per sample, the Hz and the number 1133 * of audio channels. 1134 * 1135 * Divide the result by 8 to get the byte rate. 1136 * 1137 * @returns Bitrate. 1138 * @param cBits Number of bits per sample. 1139 * @param uHz Hz (Hertz) rate. 1140 * @param cChannels Number of audio channels. 1141 */ 1142 uint32_t DrvAudioHlpCalcBitrate(uint8_t cBits, uint32_t uHz, uint8_t cChannels) 1143 { 1144 return cBits * uHz * cChannels; 1145 } 1146 1147 /** 1148 * Gets the bitrate. 1149 * 1150 * Divide the result by 8 to get the byte rate. 1151 * 1152 * @returns Bit rate. 1153 * @param pProps PCM properties to calculate bitrate for. 1154 */ 1155 uint32_t DrvAudioHlpGetBitrate(PCPDMAUDIOPCMPROPS pProps) 1156 { 1157 return DrvAudioHlpCalcBitrate(pProps->cbSample * 8, pProps->uHz, pProps->cChannels); 1158 } 1159 1160 /** 1161 * Rounds down the given byte amount to the nearest frame boundrary. 1162 * 1163 * @returns Rounded byte amount. 1164 * @param pProps PCM properties to use. 1165 * @param cb The size (in bytes) to round. 1166 */ 1167 uint32_t DrvAudioHlpFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1168 { 1169 AssertPtrReturn(pProps, 0); 1170 return PDMAUDIOPCMPROPS_F2B(pProps, PDMAUDIOPCMPROPS_B2F(pProps, cb)); 1171 } 1172 1173 /** 1174 * Checks if the given size is aligned on a frame boundrary. 1175 * 1176 * @returns @c true if properly aligned, @c false if not. 1177 * @param pProps PCM properties to use. 1178 * @param cb The size (in bytes) to check. 1179 */ 1180 bool DrvAudioHlpIsBytesAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1181 { 1182 AssertPtrReturn(pProps, false); 1183 uint32_t const cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1184 AssertReturn(cbFrame, false); 1185 return cb % cbFrame == 0; 1186 } 1187 1188 /** 1189 * Returns the bytes per second for given PCM properties. 1190 * 1191 * @returns Bytes per second. 1192 * @param pProps PCM properties to retrieve size for. 1193 */ 1194 DECLINLINE(uint64_t) drvAudioHlpBytesPerSec(PCPDMAUDIOPCMPROPS pProps) 1195 { 1196 return PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */) * pProps->uHz; 1197 } 1198 1199 /** 1200 * Converts bytes to frames (rounding down of course). 1201 * 1202 * @returns Number of frames. 1203 * @param pProps PCM properties to use. 1204 * @param cb The number of bytes to convert. 1205 */ 1206 uint32_t DrvAudioHlpBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1207 { 1208 AssertPtrReturn(pProps, 0); 1209 return PDMAUDIOPCMPROPS_B2F(pProps, cb); 1210 } 1211 1212 /** 1213 * Converts bytes to milliseconds. 1214 * 1215 * @return Number milliseconds @a cb takes to play or record. 1216 * @param pProps PCM properties to use. 1217 * @param cb The number of bytes to convert. 1218 * 1219 * @note Rounds up the result. 1220 */ 1221 uint64_t DrvAudioHlpBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1222 { 1223 AssertPtrReturn(pProps, 0); 1224 1225 /* Check parameters to prevent division by chainsaw: */ 1226 uint32_t const uHz = pProps->uHz; 1227 if (uHz) 1228 { 1229 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1230 if (cbFrame) 1231 { 1232 /* Round cb up to closest frame size: */ 1233 cb = (cb + cbFrame - 1) / cbFrame; 1234 1235 /* Convert to milliseconds. */ 1236 return (cb * (uint64_t)RT_MS_1SEC + uHz - 1) / uHz; 1237 } 1238 } 1239 return 0; 1240 } 1241 1242 /** 1243 * Converts bytes to microseconds. 1244 * 1245 * @return Number microseconds @a cb takes to play or record. 1246 * @param pProps PCM properties to use. 1247 * @param cb The number of bytes to convert. 1248 * 1249 * @note Rounds up the result. 1250 */ 1251 uint64_t DrvAudioHlpBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1252 { 1253 AssertPtrReturn(pProps, 0); 1254 1255 /* Check parameters to prevent division by chainsaw: */ 1256 uint32_t const uHz = pProps->uHz; 1257 if (uHz) 1258 { 1259 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1260 if (cbFrame) 1261 { 1262 /* Round cb up to closest frame size: */ 1263 cb = (cb + cbFrame - 1) / cbFrame; 1264 1265 /* Convert to microseconds. */ 1266 return (cb * (uint64_t)RT_US_1SEC + uHz - 1) / uHz; 1267 } 1268 } 1269 return 0; 1270 } 1271 1272 /** 1273 * Converts bytes to nanoseconds. 1274 * 1275 * @return Number nanoseconds @a cb takes to play or record. 1276 * @param pProps PCM properties to use. 1277 * @param cb The number of bytes to convert. 1278 * 1279 * @note Rounds up the result. 1280 */ 1281 uint64_t DrvAudioHlpBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1282 { 1283 AssertPtrReturn(pProps, 0); 1284 1285 /* Check parameters to prevent division by chainsaw: */ 1286 uint32_t const uHz = pProps->uHz; 1287 if (uHz) 1288 { 1289 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */); 1290 if (cbFrame) 1291 { 1292 /* Round cb up to closest frame size: */ 1293 cb = (cb + cbFrame - 1) / cbFrame; 1294 1295 /* Convert to nanoseconds. */ 1296 return (cb * (uint64_t)RT_NS_1SEC + uHz - 1) / uHz; 1297 } 1298 } 1299 return 0; 1300 } 1301 1302 /** 1303 * Converts frames to bytes. 1304 * 1305 * @return Number of bytes. 1306 * @param pProps The PCM properties to use. 1307 * @param cFrames Number of audio frames to convert. 1308 */ 1309 uint32_t DrvAudioHlpFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1310 { 1311 AssertPtrReturn(pProps, 0); 1312 return PDMAUDIOPCMPROPS_F2B(pProps, cFrames); 1313 } 1314 1315 /** 1316 * Converts frames to milliseconds. 1317 * 1318 * @returns milliseconds. 1319 * @param pProps The PCM properties to use. 1320 * @param cFrames Number of audio frames to convert. 1321 * @note No rounding here, result is floored. 1322 */ 1323 uint64_t DrvAudioHlpFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1324 { 1325 AssertPtrReturn(pProps, 0); 1326 1327 /* Check input to prevent division by chainsaw: */ 1328 uint32_t const uHz = pProps->uHz; 1329 if (uHz) 1330 return ASMMultU32ByU32DivByU32(cFrames, RT_MS_1SEC, uHz); 1331 return 0; 1332 } 1333 1334 /** 1335 * Converts frames to nanoseconds. 1336 * 1337 * @returns Nanoseconds. 1338 * @param pProps The PCM properties to use. 1339 * @param cFrames Number of audio frames to convert. 1340 * @note No rounding here, result is floored. 1341 */ 1342 uint64_t DrvAudioHlpFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1343 { 1344 AssertPtrReturn(pProps, 0); 1345 1346 /* Check input to prevent division by chainsaw: */ 1347 uint32_t const uHz = pProps->uHz; 1348 if (uHz) 1349 return ASMMultU32ByU32DivByU32(cFrames, RT_NS_1SEC, uHz); 1350 return 0; 1351 } 1352 1353 /** 1354 * Converts milliseconds to frames. 1355 * 1356 * @returns Number of frames 1357 * @param pProps The PCM properties to use. 1358 * @param cMs The number of milliseconds to convert. 1359 * 1360 * @note The result is rounded rather than floored (hysterical raisins). 1361 */ 1362 uint32_t DrvAudioHlpMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs) 1363 { 1364 AssertPtrReturn(pProps, 0); 1365 1366 uint32_t const uHz = pProps->uHz; 1367 uint32_t cFrames; 1368 if (cMs < RT_MS_1SEC) 1369 cFrames = 0; 1370 else 1371 { 1372 cFrames = cMs / RT_MS_1SEC * uHz; 1373 cMs %= RT_MS_1SEC; 1374 } 1375 cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cMs) + RT_MS_1SEC - 1) / RT_MS_1SEC; 1376 return cFrames; 1377 } 1378 1379 /** 1380 * Converts milliseconds to bytes. 1381 * 1382 * @returns Number of bytes (frame aligned). 1383 * @param pProps The PCM properties to use. 1384 * @param cMs The number of milliseconds to convert. 1385 * 1386 * @note The result is rounded rather than floored (hysterical raisins). 1387 */ 1388 uint32_t DrvAudioHlpMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs) 1389 { 1390 return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpMilliToFrames(pProps, cMs)); 1391 } 1392 1393 /** 1394 * Converts nanoseconds to frames. 1395 * 1396 * @returns Number of frames 1397 * @param pProps The PCM properties to use. 1398 * @param cNs The number of nanoseconds to convert. 1399 * 1400 * @note The result is rounded rather than floored (hysterical raisins). 1401 */ 1402 uint32_t DrvAudioHlpNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs) 1403 { 1404 AssertPtrReturn(pProps, 0); 1405 1406 uint32_t const uHz = pProps->uHz; 1407 uint32_t cFrames; 1408 if (cNs < RT_NS_1SEC) 1409 cFrames = 0; 1410 else 1411 { 1412 cFrames = cNs / RT_NS_1SEC * uHz; 1413 cNs %= RT_NS_1SEC; 1414 } 1415 cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cNs) + RT_NS_1SEC - 1) / RT_NS_1SEC; 1416 return cFrames; 1417 } 1418 1419 /** 1420 * Converts nanoseconds to bytes. 1421 * 1422 * @returns Number of bytes (frame aligned). 1423 * @param pProps The PCM properties to use. 1424 * @param cNs The number of nanoseconds to convert. 1425 * 1426 * @note The result is rounded rather than floored (hysterical raisins). 1427 */ 1428 uint32_t DrvAudioHlpNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs) 1429 { 1430 return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpNanoToFrames(pProps, cNs)); 1431 } 1439 1440 /********************************************************************************************************************************* 1441 * Audio File Helpers * 1442 *********************************************************************************************************************************/ 1432 1443 1433 1444 /**
Note:
See TracChangeset
for help on using the changeset viewer.