VirtualBox

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

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

Audio: Renaming.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.2 KB
Line 
1/* $Id: DrvAudioCommon.cpp 61167 2016-05-24 15:48:51Z 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/**
65 * Retrieves the matching PDMAUDIOFMT for given bits + signing flag.
66 *
67 * @return IPRT status code.
68 * @return PDMAUDIOFMT Resulting audio format or PDMAUDIOFMT_INVALID if invalid.
69 * @param cBits Bits to retrieve audio format for.
70 * @param fSigned Signed flag for bits to retrieve audio format for.
71 */
72PDMAUDIOFMT DrvAudioAudFmtBitsToAudFmt(uint8_t cBits, bool fSigned)
73{
74 if (fSigned)
75 {
76 switch (cBits)
77 {
78 case 8: return PDMAUDIOFMT_S8;
79 case 16: return PDMAUDIOFMT_S16;
80 case 32: return PDMAUDIOFMT_S32;
81 default: break;
82 }
83 }
84 else
85 {
86 switch (cBits)
87 {
88 case 8: return PDMAUDIOFMT_U8;
89 case 16: return PDMAUDIOFMT_U16;
90 case 32: return PDMAUDIOFMT_U32;
91 default: break;
92 }
93 }
94
95 AssertMsgFailed(("Bogus audio bits %RU8\n", cBits));
96 return PDMAUDIOFMT_INVALID;
97}
98
99/**
100 * Clears a sample buffer by the given amount of audio samples.
101 *
102 * @return IPRT status code.
103 * @param pPCMProps PCM properties to use for the buffer to clear.
104 * @param pvBuf Buffer to clear.
105 * @param cbBuf Size (in bytes) of the buffer.
106 * @param cSamples Number of audio samples to clear in the buffer.
107 */
108void DrvAudioHlpClearBuf(PPDMPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cSamples)
109{
110 AssertPtrReturnVoid(pPCMProps);
111 AssertPtrReturnVoid(pvBuf);
112
113 if (!cbBuf || !cSamples)
114 return;
115
116 Log2Func(("pPCMInfo=%p, pvBuf=%p, cSamples=%RU32, fSigned=%RTbool, cBits=%RU8, cShift=%RU8\n",
117 pPCMProps, pvBuf, cSamples, pPCMProps->fSigned, pPCMProps->cBits, pPCMProps->cShift));
118
119 if (pPCMProps->fSigned)
120 {
121 memset(pvBuf, 0, cSamples << pPCMProps->cShift);
122 }
123 else
124 {
125 switch (pPCMProps->cBits)
126 {
127 case 8:
128 {
129 memset(pvBuf, 0x80, cSamples << pPCMProps->cShift);
130 break;
131 }
132
133 case 16:
134 {
135 uint16_t *p = (uint16_t *)pvBuf;
136 int shift = pPCMProps->cChannels - 1;
137 short s = INT16_MAX;
138
139 if (pPCMProps->fSwapEndian)
140 s = RT_BSWAP_U16(s);
141
142 for (unsigned i = 0; i < cSamples << shift; i++)
143 p[i] = s;
144
145 break;
146 }
147
148 case 32:
149 {
150 uint32_t *p = (uint32_t *)pvBuf;
151 int shift = pPCMProps->cChannels - 1;
152 int32_t s = INT32_MAX;
153
154 if (pPCMProps->fSwapEndian)
155 s = RT_BSWAP_U32(s);
156
157 for (unsigned i = 0; i < cSamples << shift; i++)
158 p[i] = s;
159
160 break;
161 }
162
163 default:
164 {
165 AssertMsgFailed(("Invalid bits: %RU8\n", pPCMProps->cBits));
166 break;
167 }
168 }
169 }
170}
171
172const char *DrvAudHlpRecSrcToStr(PDMAUDIORECSOURCE enmRecSrc)
173{
174 switch (enmRecSrc)
175 {
176 case PDMAUDIORECSOURCE_MIC: return "Microphone In";
177 case PDMAUDIORECSOURCE_CD: return "CD";
178 case PDMAUDIORECSOURCE_VIDEO: return "Video";
179 case PDMAUDIORECSOURCE_AUX: return "AUX";
180 case PDMAUDIORECSOURCE_LINE: return "Line In";
181 case PDMAUDIORECSOURCE_PHONE: return "Phone";
182 default:
183 break;
184 }
185
186 AssertMsgFailed(("Invalid recording source %ld\n", enmRecSrc));
187 return "Unknown";
188}
189
190/**
191 * Returns wether the given audio format has signed bits or not.
192 *
193 * @return IPRT status code.
194 * @return bool @true for signed bits, @false for unsigned.
195 * @param enmFmt Audio format to retrieve value for.
196 */
197bool DrvAudioHlpAudFmtIsSigned(PDMAUDIOFMT enmFmt)
198{
199 switch (enmFmt)
200 {
201 case PDMAUDIOFMT_S8:
202 case PDMAUDIOFMT_S16:
203 case PDMAUDIOFMT_S32:
204 return true;
205
206 case PDMAUDIOFMT_U8:
207 case PDMAUDIOFMT_U16:
208 case PDMAUDIOFMT_U32:
209 return false;
210
211 default:
212 break;
213 }
214
215 AssertMsgFailed(("Bogus audio format %ld\n", enmFmt));
216 return false;
217}
218
219/**
220 * Returns the bits of a given audio format.
221 *
222 * @return IPRT status code.
223 * @return uint8_t Bits of audio format.
224 * @param enmFmt Audio format to retrieve value for.
225 */
226uint8_t DrvAudioHlpAudFmtToBits(PDMAUDIOFMT enmFmt)
227{
228 switch (enmFmt)
229 {
230 case PDMAUDIOFMT_S8:
231 case PDMAUDIOFMT_U8:
232 return 8;
233
234 case PDMAUDIOFMT_U16:
235 case PDMAUDIOFMT_S16:
236 return 16;
237
238 case PDMAUDIOFMT_U32:
239 case PDMAUDIOFMT_S32:
240 return 32;
241
242 default:
243 break;
244 }
245
246 AssertMsgFailed(("Bogus audio format %ld\n", enmFmt));
247 return 0;
248}
249
250const char *DrvAudioHlpAudFmtToStr(PDMAUDIOFMT enmFmt)
251{
252 switch (enmFmt)
253 {
254 case PDMAUDIOFMT_U8:
255 return "U8";
256
257 case PDMAUDIOFMT_U16:
258 return "U16";
259
260 case PDMAUDIOFMT_U32:
261 return "U32";
262
263 case PDMAUDIOFMT_S8:
264 return "S8";
265
266 case PDMAUDIOFMT_S16:
267 return "S16";
268
269 case PDMAUDIOFMT_S32:
270 return "S32";
271
272 default:
273 break;
274 }
275
276 AssertMsgFailed(("Bogus audio format %ld\n", enmFmt));
277 return "Invalid";
278}
279
280PDMAUDIOFMT DrvAudioHlpStrToAudFmt(const char *pszFmt)
281{
282 AssertPtrReturn(pszFmt, PDMAUDIOFMT_INVALID);
283
284 if (!RTStrICmp(pszFmt, "u8"))
285 return PDMAUDIOFMT_U8;
286 else if (!RTStrICmp(pszFmt, "u16"))
287 return PDMAUDIOFMT_U16;
288 else if (!RTStrICmp(pszFmt, "u32"))
289 return PDMAUDIOFMT_U32;
290 else if (!RTStrICmp(pszFmt, "s8"))
291 return PDMAUDIOFMT_S8;
292 else if (!RTStrICmp(pszFmt, "s16"))
293 return PDMAUDIOFMT_S16;
294 else if (!RTStrICmp(pszFmt, "s32"))
295 return PDMAUDIOFMT_S32;
296
297 AssertMsgFailed(("Invalid audio format \"%s\"\n", pszFmt));
298 return PDMAUDIOFMT_INVALID;
299}
300
301bool DrvAudioHlpPCMPropsAreEqual(PPDMPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
302{
303 AssertPtrReturn(pProps, false);
304 AssertPtrReturn(pCfg, false);
305
306 int cBits = 8;
307 bool fSigned = false;
308
309 switch (pCfg->enmFormat)
310 {
311 case PDMAUDIOFMT_S8:
312 fSigned = true;
313 case PDMAUDIOFMT_U8:
314 break;
315
316 case PDMAUDIOFMT_S16:
317 fSigned = true;
318 case PDMAUDIOFMT_U16:
319 cBits = 16;
320 break;
321
322 case PDMAUDIOFMT_S32:
323 fSigned = true;
324 case PDMAUDIOFMT_U32:
325 cBits = 32;
326 break;
327
328 default:
329 AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
330 break;
331 }
332
333 bool fEqual = pProps->uHz == pCfg->uHz
334 && pProps->cChannels == pCfg->cChannels
335 && pProps->fSigned == fSigned
336 && pProps->cBits == cBits
337 && pProps->fSwapEndian == !(pCfg->enmEndianness == PDMAUDIOHOSTENDIANNESS);
338 return fEqual;
339}
340
341bool DrvAudioHlpPCMPropsAreEqual(PPDMPCMPROPS pProps1, PPDMPCMPROPS pProps2)
342{
343 AssertPtrReturn(pProps1, false);
344 AssertPtrReturn(pProps2, false);
345
346 return pProps1->uHz == pProps2->uHz
347 && pProps1->cChannels == pProps2->cChannels
348 && pProps1->fSigned == pProps2->fSigned
349 && pProps1->cBits == pProps2->cBits
350 && pProps1->fSwapEndian == pProps2->fSwapEndian;
351}
352
353/**
354 * Converts PCM properties to a audio stream configuration.
355 *
356 * @return IPRT status code.
357 * @param pPCMProps Pointer to PCM properties to convert.
358 * @param pCfg Pointer to audio stream configuration to store result into.
359 */
360int DrvAudioHlpPCMPropsToStreamCfg(PPDMPCMPROPS pPCMProps, PPDMAUDIOSTREAMCFG pCfg)
361{
362 AssertPtrReturn(pPCMProps, VERR_INVALID_POINTER);
363 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
364
365 pCfg->uHz = pPCMProps->uHz;
366 pCfg->cChannels = pPCMProps->cChannels;
367 pCfg->enmFormat = DrvAudioAudFmtBitsToAudFmt(pPCMProps->cBits, pPCMProps->fSigned);
368
369 /** @todo We assume little endian is the default for now. */
370 pCfg->enmEndianness = pPCMProps->fSwapEndian == false ? PDMAUDIOENDIANNESS_LITTLE : PDMAUDIOENDIANNESS_BIG;
371 return VINF_SUCCESS;
372}
373
374bool DrvAudioHlpStreamCfgIsValid(PPDMAUDIOSTREAMCFG pCfg)
375{
376 bool fValid = ( pCfg->cChannels == 1
377 || pCfg->cChannels == 2); /* Either stereo (2) or mono (1), per stream. */
378
379 fValid |= ( pCfg->enmEndianness == PDMAUDIOENDIANNESS_LITTLE
380 || pCfg->enmEndianness == PDMAUDIOENDIANNESS_BIG);
381
382 fValid |= ( pCfg->enmDir == PDMAUDIODIR_IN
383 || pCfg->enmDir == PDMAUDIODIR_OUT);
384
385 if (fValid)
386 {
387 switch (pCfg->enmFormat)
388 {
389 case PDMAUDIOFMT_S8:
390 case PDMAUDIOFMT_U8:
391 case PDMAUDIOFMT_S16:
392 case PDMAUDIOFMT_U16:
393 case PDMAUDIOFMT_S32:
394 case PDMAUDIOFMT_U32:
395 break;
396 default:
397 fValid = false;
398 break;
399 }
400 }
401
402 /** @todo Check for defined frequencies supported. */
403 fValid |= pCfg->uHz > 0;
404
405 return fValid;
406}
407
408/**
409 * Converts an audio stream configuration to matching PCM properties.
410 *
411 * @return IPRT status code.
412 * @param pCfg Audio stream configuration to convert.
413 * @param pProps PCM properties to save result to.
414 */
415int DrvAudioHlpStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps)
416{
417 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
418 AssertPtrReturn(pProps, VERR_INVALID_POINTER);
419
420 int rc = VINF_SUCCESS;
421
422 int cBits = 8, cShift = 0;
423 bool fSigned = false;
424
425 switch (pCfg->enmFormat)
426 {
427 case PDMAUDIOFMT_S8:
428 fSigned = true;
429 case PDMAUDIOFMT_U8:
430 break;
431
432 case PDMAUDIOFMT_S16:
433 fSigned = true;
434 case PDMAUDIOFMT_U16:
435 cBits = 16;
436 cShift = 1;
437 break;
438
439 case PDMAUDIOFMT_S32:
440 fSigned = true;
441 case PDMAUDIOFMT_U32:
442 cBits = 32;
443 cShift = 2;
444 break;
445
446 default:
447 AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
448 rc = VERR_NOT_SUPPORTED;
449 break;
450 }
451
452 if (RT_SUCCESS(rc))
453 {
454 pProps->uHz = pCfg->uHz;
455 pProps->cBits = cBits;
456 pProps->fSigned = fSigned;
457 pProps->cChannels = pCfg->cChannels;
458 pProps->cShift = (pCfg->cChannels == 2) + cShift;
459 pProps->uAlign = (1 << pProps->cShift) - 1;
460 pProps->cbPerSec = pProps->uHz << pProps->cShift;
461 pProps->fSwapEndian = pCfg->enmEndianness != PDMAUDIOHOSTENDIANNESS;
462 }
463
464 return rc;
465}
466
467void DrvAudioHlpStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg)
468{
469 AssertPtrReturnVoid(pCfg);
470
471 LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=", pCfg->uHz, pCfg->cChannels));
472
473 switch (pCfg->enmFormat)
474 {
475 case PDMAUDIOFMT_S8:
476 LogFlow(("S8"));
477 break;
478 case PDMAUDIOFMT_U8:
479 LogFlow(("U8"));
480 break;
481 case PDMAUDIOFMT_S16:
482 LogFlow(("S16"));
483 break;
484 case PDMAUDIOFMT_U16:
485 LogFlow(("U16"));
486 break;
487 case PDMAUDIOFMT_S32:
488 LogFlow(("S32"));
489 break;
490 case PDMAUDIOFMT_U32:
491 LogFlow(("U32"));
492 break;
493 default:
494 LogFlow(("invalid(%d)", pCfg->enmFormat));
495 break;
496 }
497
498 LogFlow((", endianness="));
499 switch (pCfg->enmEndianness)
500 {
501 case PDMAUDIOENDIANNESS_LITTLE:
502 LogFlow(("little\n"));
503 break;
504 case PDMAUDIOENDIANNESS_BIG:
505 LogFlow(("big\n"));
506 break;
507 default:
508 LogFlow(("invalid\n"));
509 break;
510 }
511}
512
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