VirtualBox

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

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

Audio: Update on infrastructure:

  • More work on HDA stream interleaving + surround support
  • The mixer can now (optionally) act as a supplemental layer between audio connector interface and device emulation (where applicable)
  • Multiple LUN streams can be bound to a certain sink, which in turn then can be treated as separate input/output channels
  • Unified more code which was duplicated between different audio device emulations
  • Tiny bit of documentation

Work in progress.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1/* $Id: DrvAudioCommon.cpp 60925 2016-05-10 13:27:44Z 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 int cBits = 8;
208 bool fSigned = false;
209
210 switch (pCfg->enmFormat)
211 {
212 case PDMAUDIOFMT_S8:
213 fSigned = true;
214 case PDMAUDIOFMT_U8:
215 break;
216
217 case PDMAUDIOFMT_S16:
218 fSigned = true;
219 case PDMAUDIOFMT_U16:
220 cBits = 16;
221 break;
222
223 case PDMAUDIOFMT_S32:
224 fSigned = true;
225 case PDMAUDIOFMT_U32:
226 cBits = 32;
227 break;
228
229 default:
230 AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
231 break;
232 }
233
234 bool fEqual = pProps->uHz == pCfg->uHz
235 && pProps->cChannels == pCfg->cChannels
236 && pProps->fSigned == fSigned
237 && pProps->cBits == cBits
238 && pProps->fSwapEndian == !(pCfg->enmEndianness == PDMAUDIOHOSTENDIANNESS);
239 return fEqual;
240}
241
242/**
243 * Converts an audio stream configuration to matching PCM properties.
244 *
245 * @return IPRT status code.
246 * @param pCfg Audio stream configuration to convert.
247 * @param pProps PCM properties to save result to.
248 */
249int DrvAudioStreamCfgToProps(PPDMAUDIOSTREAMCFG pCfg, PPDMPCMPROPS pProps)
250{
251 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
252 AssertPtrReturn(pProps, VERR_INVALID_POINTER);
253
254 int rc = VINF_SUCCESS;
255
256 int cBits = 8, cShift = 0;
257 bool fSigned = false;
258
259 switch (pCfg->enmFormat)
260 {
261 case PDMAUDIOFMT_S8:
262 fSigned = true;
263 case PDMAUDIOFMT_U8:
264 break;
265
266 case PDMAUDIOFMT_S16:
267 fSigned = true;
268 case PDMAUDIOFMT_U16:
269 cBits = 16;
270 cShift = 1;
271 break;
272
273 case PDMAUDIOFMT_S32:
274 fSigned = true;
275 case PDMAUDIOFMT_U32:
276 cBits = 32;
277 cShift = 2;
278 break;
279
280 default:
281 AssertMsgFailed(("Unknown format %ld\n", pCfg->enmFormat));
282 rc = VERR_NOT_SUPPORTED;
283 break;
284 }
285
286 if (RT_SUCCESS(rc))
287 {
288 pProps->uHz = pCfg->uHz;
289 pProps->cBits = cBits;
290 pProps->fSigned = fSigned;
291 pProps->cChannels = pCfg->cChannels;
292 pProps->cShift = (pCfg->cChannels == 2) + cShift;
293 pProps->uAlign = (1 << pProps->cShift) - 1;
294 pProps->cbPerSec = pProps->uHz << pProps->cShift;
295 pProps->fSwapEndian = pCfg->enmEndianness != PDMAUDIOHOSTENDIANNESS;
296 }
297
298 return rc;
299}
300
301void DrvAudioStreamCfgPrint(PPDMAUDIOSTREAMCFG pCfg)
302{
303 AssertPtrReturnVoid(pCfg);
304
305 LogFlowFunc(("uHz=%RU32, cChannels=%RU8, enmFormat=", pCfg->uHz, pCfg->cChannels));
306
307 switch (pCfg->enmFormat)
308 {
309 case PDMAUDIOFMT_S8:
310 LogFlow(("S8"));
311 break;
312 case PDMAUDIOFMT_U8:
313 LogFlow(("U8"));
314 break;
315 case PDMAUDIOFMT_S16:
316 LogFlow(("S16"));
317 break;
318 case PDMAUDIOFMT_U16:
319 LogFlow(("U16"));
320 break;
321 case PDMAUDIOFMT_S32:
322 LogFlow(("S32"));
323 break;
324 case PDMAUDIOFMT_U32:
325 LogFlow(("U32"));
326 break;
327 default:
328 LogFlow(("invalid(%d)", pCfg->enmFormat));
329 break;
330 }
331
332 LogFlow((", endianness="));
333 switch (pCfg->enmEndianness)
334 {
335 case PDMAUDIOENDIANNESS_LITTLE:
336 LogFlow(("little\n"));
337 break;
338 case PDMAUDIOENDIANNESS_BIG:
339 LogFlow(("big\n"));
340 break;
341 default:
342 LogFlow(("invalid\n"));
343 break;
344 }
345}
346
Note: See TracBrowser for help on using the repository browser.

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