VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp@ 61126

Last change on this file since 61126 was 61050, checked in by vboxsync, 9 years ago

Audio: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: DrvAudioCommon.cpp 61050 2016-05-19 15:26:50Z vboxsync $ */
2/** @file
3 * Intermedia audio driver, common routines. These are also used
4 * in the drivers which are bound to Main, e.g. the VRDE or the
5 * video audio recording drivers.
6 */
7
8/*
9 * Copyright (C) 2006-2016 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 * --------------------------------------------------------------------
19 *
20 * This code is based on: audio_template.h from QEMU AUDIO subsystem.
21 *
22 * QEMU Audio subsystem header
23 *
24 * Copyright (c) 2005 Vassili Karpov (malc)
25 *
26 * Permission is hereby granted, free of charge, to any person obtaining a copy
27 * of this software and associated documentation files (the "Software"), to deal
28 * in the Software without restriction, including without limitation the rights
29 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
30 * copies of the Software, and to permit persons to whom the Software is
31 * furnished to do so, subject to the following conditions:
32 *
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
39 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
42 * THE SOFTWARE.
43 */
44#define LOG_GROUP LOG_GROUP_DRV_AUDIO
45#include <VBox/log.h>
46#include <iprt/asm-math.h>
47#include <iprt/assert.h>
48#include <iprt/uuid.h>
49#include <iprt/string.h>
50#include <iprt/alloc.h>
51
52#include <VBox/vmm/pdmdev.h>
53#include <VBox/vmm/pdm.h>
54#include <VBox/err.h>
55#include <VBox/vmm/mm.h>
56
57#include <ctype.h>
58#include <stdlib.h>
59
60#include "DrvAudio.h"
61#include "AudioMixBuffer.h"
62
63/**
64 * Clears a sample buffer by the given amount of audio samples.
65 *
66 * @return IPRT status code.
67 * @param pPCMProps PCM properties to use for the buffer to clear.
68 * @param pvBuf Buffer to clear.
69 * @param cbBuf Size (in bytes) of the buffer.
70 * @param cSamples Number of audio samples to clear in the buffer.
71 */
72void DrvAudioClearBuf(PPDMPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples)
73{
74 AssertPtrReturnVoid(pPCMProps);
75 AssertPtrReturnVoid(pvBuf);
76
77 if (!cbBuf || !cSamples)
78 return;
79
80 Log2Func(("pPCMInfo=%p, pvBuf=%p, cSamples=%RU32, fSigned=%RTbool, cBits=%RU8, cShift=%RU8\n",
81 pPCMProps, pvBuf, cSamples, pPCMProps->fSigned, pPCMProps->cBits, pPCMProps->cShift));
82
83 if (pPCMProps->fSigned)
84 {
85 memset(pvBuf, 0, cSamples << pPCMProps->cShift);
86 }
87 else
88 {
89 switch (pPCMProps->cBits)
90 {
91 case 8:
92 {
93 memset(pvBuf, 0x80, cSamples << pPCMProps->cShift);
94 break;
95 }
96
97 case 16:
98 {
99 uint16_t *p = (uint16_t *)pvBuf;
100 int shift = pPCMProps->cChannels - 1;
101 short s = INT16_MAX;
102
103 if (pPCMProps->fSwapEndian)
104 s = RT_BSWAP_U16(s);
105
106 for (unsigned i = 0; i < cSamples << shift; i++)
107 p[i] = s;
108
109 break;
110 }
111
112 case 32:
113 {
114 uint32_t *p = (uint32_t *)pvBuf;
115 int shift = pPCMProps->cChannels - 1;
116 int32_t s = INT32_MAX;
117
118 if (pPCMProps->fSwapEndian)
119 s = RT_BSWAP_U32(s);
120
121 for (unsigned i = 0; i < cSamples << shift; i++)
122 p[i] = s;
123
124 break;
125 }
126
127 default:
128 {
129 AssertMsgFailed(("Invalid bits: %RU8\n", pPCMProps->cBits));
130 break;
131 }
132 }
133 }
134}
135
136const char *DrvAudRecSrcToStr(PDMAUDIORECSOURCE enmRecSrc)
137{
138 switch (enmRecSrc)
139 {
140 case PDMAUDIORECSOURCE_MIC: return "Microphone In";
141 case PDMAUDIORECSOURCE_CD: return "CD";
142 case PDMAUDIORECSOURCE_VIDEO: return "Video";
143 case PDMAUDIORECSOURCE_AUX: return "AUX";
144 case PDMAUDIORECSOURCE_LINE: return "Line In";
145 case PDMAUDIORECSOURCE_PHONE: return "Phone";
146 default:
147 break;
148 }
149
150 AssertMsgFailed(("Invalid recording source %ld\n", enmRecSrc));
151 return "Unknown";
152}
153
154const char *DrvAudioAudFmtToStr(PDMAUDIOFMT enmFmt)
155{
156 switch (enmFmt)
157 {
158 case PDMAUDIOFMT_U8:
159 return "U8";
160
161 case PDMAUDIOFMT_U16:
162 return "U16";
163
164 case PDMAUDIOFMT_U32:
165 return "U32";
166
167 case PDMAUDIOFMT_S8:
168 return "S8";
169
170 case PDMAUDIOFMT_S16:
171 return "S16";
172
173 case PDMAUDIOFMT_S32:
174 return "S32";
175
176 default:
177 break;
178 }
179
180 AssertMsgFailed(("Bogus audio format %ld\n", enmFmt));
181 return "Invalid";
182}
183
184PDMAUDIOFMT DrvAudioStrToAudFmt(const char *pszFmt)
185{
186 AssertPtrReturn(pszFmt, PDMAUDIOFMT_INVALID);
187
188 if (!RTStrICmp(pszFmt, "u8"))
189 return PDMAUDIOFMT_U8;
190 else if (!RTStrICmp(pszFmt, "u16"))
191 return PDMAUDIOFMT_U16;
192 else if (!RTStrICmp(pszFmt, "u32"))
193 return PDMAUDIOFMT_U32;
194 else if (!RTStrICmp(pszFmt, "s8"))
195 return PDMAUDIOFMT_S8;
196 else if (!RTStrICmp(pszFmt, "s16"))
197 return PDMAUDIOFMT_S16;
198 else if (!RTStrICmp(pszFmt, "s32"))
199 return PDMAUDIOFMT_S32;
200
201 AssertMsgFailed(("Invalid audio format \"%s\"\n", pszFmt));
202 return PDMAUDIOFMT_INVALID;
203}
204
205bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
206{
207 AssertPtrReturn(pProps, VERR_INVALID_POINTER);
208 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
209
210 int cBits = 8;
211 bool fSigned = false;
212
213 switch (pCfg->enmFormat)
214 {
215 case PDMAUDIOFMT_S8:
216 fSigned = true;
217 case PDMAUDIOFMT_U8:
218 break;
219
220 case PDMAUDIOFMT_S16:
221 fSigned = true;
222 case PDMAUDIOFMT_U16:
223 cBits = 16;
224 break;
225
226 case PDMAUDIOFMT_S32:
227 fSigned = true;
228 case PDMAUDIOFMT_U32:
229 cBits = 32;
230 break;
231
232 default:
233 AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
234 break;
235 }
236
237 bool fEqual = pProps->uHz == pCfg->uHz
238 && pProps->cChannels == pCfg->cChannels
239 && pProps->fSigned == fSigned
240 && pProps->cBits == cBits
241 && pProps->fSwapEndian == !(pCfg->enmEndianness == PDMAUDIOHOSTENDIANNESS);
242 return fEqual;
243}
244
245bool DrvAudioPCMPropsAreEqual(PPDMPCMPROPS pProps1, PPDMPCMPROPS pProps2)
246{
247 AssertPtrReturn(pProps1, VERR_INVALID_POINTER);
248 AssertPtrReturn(pProps2, VERR_INVALID_POINTER);
249
250 return pProps1->uHz == pProps2->uHz
251 && pProps1->cChannels == pProps2->cChannels
252 && pProps1->fSigned == pProps2->fSigned
253 && pProps1->cBits == pProps2->cBits
254 && pProps1->fSwapEndian == pProps2->fSwapEndian;
255}
256
257/**
258 * Converts an audio stream configuration to matching PCM properties.
259 *
260 * @return IPRT status code.
261 * @param pCfg Audio stream configuration to convert.
262 * @param pProps PCM properties to save result to.
263 */
264int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps)
265{
266 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
267 AssertPtrReturn(pProps, VERR_INVALID_POINTER);
268
269 int rc = VINF_SUCCESS;
270
271 int cBits = 8, cShift = 0;
272 bool fSigned = false;
273
274 switch (pCfg->enmFormat)
275 {
276 case PDMAUDIOFMT_S8:
277 fSigned = true;
278 case PDMAUDIOFMT_U8:
279 break;
280
281 case PDMAUDIOFMT_S16:
282 fSigned = true;
283 case PDMAUDIOFMT_U16:
284 cBits = 16;
285 cShift = 1;
286 break;
287
288 case PDMAUDIOFMT_S32:
289 fSigned = true;
290 case PDMAUDIOFMT_U32:
291 cBits = 32;
292 cShift = 2;
293 break;
294
295 default:
296 AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
297 rc = VERR_NOT_SUPPORTED;
298 break;
299 }
300
301 if (RT_SUCCESS(rc))
302 {
303 pProps->uHz = pCfg->uHz;
304 pProps->cBits = cBits;
305 pProps->fSigned = fSigned;
306 pProps->cChannels = pCfg->cChannels;
307 pProps->cShift = (pCfg->cChannels == 2) + cShift;
308 pProps->uAlign = (1 << pProps->cShift) - 1;
309 pProps->cbPerSec = pProps->uHz << pProps->cShift;
310 pProps->fSwapEndian = pCfg->enmEndianness != PDMAUDIOHOSTENDIANNESS;
311 }
312
313 return rc;
314}
315
316void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg)
317{
318 AssertPtrReturnVoid(pCfg);
319
320 LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=", pCfg->uHz, pCfg->cChannels));
321
322 switch (pCfg->enmFormat)
323 {
324 case PDMAUDIOFMT_S8:
325 LogFlow(("S8"));
326 break;
327 case PDMAUDIOFMT_U8:
328 LogFlow(("U8"));
329 break;
330 case PDMAUDIOFMT_S16:
331 LogFlow(("S16"));
332 break;
333 case PDMAUDIOFMT_U16:
334 LogFlow(("U16"));
335 break;
336 case PDMAUDIOFMT_S32:
337 LogFlow(("S32"));
338 break;
339 case PDMAUDIOFMT_U32:
340 LogFlow(("U32"));
341 break;
342 default:
343 LogFlow(("invalid(%d)", pCfg->enmFormat));
344 break;
345 }
346
347 LogFlow((", endianness="));
348 switch (pCfg->enmEndianness)
349 {
350 case PDMAUDIOENDIANNESS_LITTLE:
351 LogFlow(("little\n"));
352 break;
353 case PDMAUDIOENDIANNESS_BIG:
354 LogFlow(("big\n"));
355 break;
356 default:
357 LogFlow(("invalid\n"));
358 break;
359 }
360}
361
Note: See TracBrowser for help on using the repository browser.

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