source: contrib/API/lib/pcmmulti.c

Last change on this file was 578, checked in by David Azarewicz, 11 years ago

API updates

File size: 38.2 KB
Line 
1/*
2 * This file is part of uniaud.dll.
3 *
4 * Copyright (c) 2010 Mensys BV
5 * Copyright (c) 2007 Vlad Stelmahovsky aka Vladest
6 *
7 * This library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License and the GNU General Public License along with this library.
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21#define INCL_DOS
22#define INCL_DOSERRORS
23#include <os2.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <io.h>
27#include <fcntl.h>
28#include <conio.h>
29#include <math.h>
30#include <string.h>
31
32#include "uniaud.h"
33#include "unidef.h"
34#include "errno.h"
35#include "internal.h"
36
37
38chan_convert_table_t nforce_chan_convert_table =
39{
40 {0, 1, 2, 3, 4, 5, 0, 0}, /* source */
41 {0, 1, 2, 3, 4, 5, 0, 0} /* destination */
42};
43
44chan_convert_table_t cmedia_chan_convert_table =
45{
46 {0, 1, 2, 3, 4, 5, 0, 0}, /* source */
47 {0, 1, 4, 5, 2, 3, 0, 0} /* destination */
48};
49
50static struct card_type_id_table_s {
51 char *driver;
52 card_type_ids card_type_id;
53 chan_convert_table_t *chan_convert_table;
54} card_type_id_table[] =
55{
56 "EMU10K1", UNIAUD_TYPE_ID_EMU10K1, NULL,
57 "Audigy", UNIAUD_TYPE_ID_AUDIGY, NULL,
58 "Audigy2", UNIAUD_TYPE_ID_AUDIGY2, NULL,
59 "CMI8738-MC6", UNIAUD_TYPE_ID_CMI8738, &cmedia_chan_convert_table,
60 "CMI8738-MC4", UNIAUD_TYPE_ID_CMI8738, NULL,
61 "CMI8738", UNIAUD_TYPE_ID_CMI8738, &cmedia_chan_convert_table,
62 "CMI8338", UNIAUD_TYPE_ID_CMI8338, NULL,
63 "CMIPCI", UNIAUD_TYPE_ID_CMI, &cmedia_chan_convert_table,
64 "YMF724", UNIAUD_TYPE_ID_YMF724, NULL,
65 "YMF724F", UNIAUD_TYPE_ID_YMF724F, NULL,
66 "YMF740", UNIAUD_TYPE_ID_YMF740, NULL,
67 "YMF740C", UNIAUD_TYPE_ID_YMF740C, NULL,
68 "YMF744", UNIAUD_TYPE_ID_YMF744, NULL,
69 "YMF754", UNIAUD_TYPE_ID_YMF754, NULL,
70 "CA0108", UNIAUD_TYPE_ID_AUDIGYLS, NULL,
71 "FM801", UNIAUD_TYPE_ID_FM801, NULL,
72 "NFORCE", UNIAUD_TYPE_ID_NFORCE, /*&nforce_chan_convert_table*/NULL,
73 "ICH", UNIAUD_TYPE_ID_ICH, NULL,
74 "ICH4", UNIAUD_TYPE_ID_ICH4, NULL,
75 "ICH5", UNIAUD_TYPE_ID_ICH5, NULL,
76 "VIA8233A", UNIAUD_TYPE_ID_VIA8233A, NULL,
77 "VIA8237", UNIAUD_TYPE_ID_VIA8237, NULL,
78 "VIA8233", UNIAUD_TYPE_ID_VIA8233, NULL,
79 0, 0, 0
80};
81
82#include "fastmemcpy.h"
83/*
84 * Sad story about Creative:
85 * for routing table we have to set up
86 * table for each substream
87 * for example: we have 6ch, so have to create 3 stereo substreams
88 * each substream has own index (from 0 to 31)
89 * so we created 3 stereo substreams with indexes from 0 to 2
90 * now we have to say to each substream - to which output it have
91 * to be connected.
92 * each substream have routing with 12 (for audigy 16 and 24 for audigy2)
93 * values
94 * for sb live: first 4 means mono, second is right and third 4 is left
95 * channels
96 * we have to put for left and right channels numbers of fx-buses, to
97 * which they will be connected phisycally
98 * for sb live:
99 * fx phys channel
100 *
101 * 0x00 PCM Left - not sure about this
102 * 0x01 PCM Right
103 * 0x02 PCM Surround Left
104 * 0x03 PCM Surround Right
105 * 0x04 MIDI Left
106 * 0x05 MIDI Right
107 * 0x06 Center
108 * 0x07 LFE
109 */
110static int uniaud_mixer_sblive_set(int card_id, int channels)
111{
112 int i, index, ret=0;
113// int vol_def[12] = {255, 255, 0, 0, 255, 0, 0, 0, 0, 255, 0, 0 };
114 int vol_4_ch[12] = {0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0 };
115 int vol_6_ch[12] = {0, 0, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0 };
116 int vol_def[12] = {255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0 };
117// int vol_4_ch[12] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
118// int vol_6_ch[12] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
119 int routing_def[12] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
120 int routing_rear[12] = { 0, 0, 0, 0, 4, 4, 0, 0, 1, 1, 0, 0 };
121 int routing_front[12] = { 0, 0, 0, 0, 2, 2, 0, 0, 3, 3, 0, 0 };
122 int routing_lfe[12] = { 0, 0, 0, 0, 6, 6, 0, 0, 7, 7, 0, 0 };
123// int routing_front[12] = { 8, 9, 0, 0, 8, 9, 0, 0, 8, 9, 0, 0 };
124// int routing_rear[12] = { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
125// int routing_lfe[12] = { 6, 7, 0, 0, 6, 7, 0, 0, 6, 7, 0, 0 };
126
127 for (index=0; index < 3; index++)
128 {
129 for (i=0; i < 12; i++)
130 {
131 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, index)) < 0)
132 return ret;
133 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",/*routing_def*/routing_front[i], i, index)) < 0)
134 return ret;
135 }
136 }
137 if (channels <= 2)
138 {
139 for (i=0; i < 12; i++)
140 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, 0)) < 0)
141 return ret;
142 for (i=0; i < 12; i++)
143 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_def[i], i, 0)) < 0)
144 return ret;
145 }
146
147 if (channels >= 4)
148 {
149 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 0, 0)) < 0)
150 return ret;
151 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 1, 0)) < 0)
152 return ret;
153 for (i=0; i < 12; i++)
154 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_4_ch[i], i, 1)) < 0)
155 return ret;
156#if 1
157 for (i=0; i < 12; i++)
158 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_rear[i], i, 1)) < 0)
159 return ret;
160#endif
161 }
162
163 if (channels == 6)
164 {
165 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Center Playback Volume",0, 0, 0)) < 0)
166 return ret;
167 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave LFE Playback Volume",0, 0, 0)) < 0)
168 return ret;
169 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone Center Playback Switch",1, 0, 1)) < 0)
170 return ret;
171 if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone LFE Playback Switch",1, 0, 1)) < 0)
172 return ret;
173
174 for (i=0; i < 12; i++)
175 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_6_ch[i], i, 2)) < 0)
176 return ret;
177 for (i=0; i < 12; i++)
178 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_lfe[i], i, 2)) < 0)
179 return ret;
180 }
181
182// if ((ret = uniaud_mixer_put_value_by_name(card_id,"SB Live Analog/Digital Output Jack",0,0,0) < 0)
183// printf("err10\n");
184
185 return ret;
186}
187
188static int uniaud_mixer_audigy_set(int card_id, int channels)
189{
190 int i, index, ret=0;
191 int vol_def[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
192 int vol_4_ch[24] = {0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 };
193 int vol_6_ch[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
194 int routing_def[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
195 //int routing_front[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
196 //int routing_rear[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
197 int routing_lfe[24] = { 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0 };
198
199 for (index=0; index < 3; index++)
200 {
201 for (i=0; i < 24; i++)
202 {
203 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, index)) < 0)
204 return ret;
205 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_def[i], i, index)) < 0)
206 return ret;
207 }
208 }
209
210 if (channels >= 4)
211 {
212// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 0, 0)) < 0)
213// return ret;
214// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 1, 0)) < 0)
215// return ret;
216 for (i=0; i < 24; i++)
217 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_4_ch[i], i, 1)) < 0)
218 return ret;
219 }
220
221 if (channels == 6)
222 {
223// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Center Playback Volume",0, 0, 0)) < 0)
224// return ret;
225// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave LFE Playback Volume",0, 0, 0)) < 0)
226// return ret;
227// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone Center Playback Switch",1, 0, 1)) < 0)
228// return ret;
229// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone LFE Playback Switch",1, 0, 1)) < 0)
230// return ret;
231
232 for (i=0; i < 24; i++)
233 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_6_ch[i], i, 2)) < 0)
234 return ret;
235 for (i=0; i < 24; i++)
236 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_lfe[i], i, 2)) < 0)
237 return ret;
238 }
239
240// if ((ret = uniaud_mixer_put_value_by_name(card_id,"SB Live Analog/Digital Output Jack",0,0,0) < 0)
241// printf("err10\n");
242
243 return ret;
244}
245
246static int uniaud_mixer_audigy2_set(int card_id, int channels)
247{
248 int i, index, ret=0;
249 int vol_def[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
250 int vol_4_ch[24] = {0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0 };
251 int vol_6_ch[24] = {255, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 };
252 int routing_def[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
253 //int routing_front[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
254 //int routing_rear[24] = { 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0 };
255 int routing_lfe[24] = { 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0 };
256
257 for (index=0; index < 3; index++)
258 {
259 for (i=0; i < 24; i++)
260 {
261 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_def[i], i, index)) < 0)
262 return ret;
263 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_def[i], i, index)) < 0)
264 return ret;
265 }
266 }
267
268 if (channels >= 4)
269 {
270// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 0, 0)) < 0)
271// return ret;
272// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Surround Playback Volume",0, 1, 0)) < 0)
273// return ret;
274 for (i=0; i < 24; i++)
275 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_4_ch[i], i, 1)) < 0)
276 return ret;
277 }
278
279 if (channels == 6)
280 {
281// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave Center Playback Volume",0, 0, 0)) < 0)
282// return ret;
283// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Wave LFE Playback Volume",0, 0, 0)) < 0)
284// return ret;
285// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone Center Playback Switch",1, 0, 1)) < 0)
286// return ret;
287// if ((ret = uniaud_mixer_put_value_by_name(card_id,"Headphone LFE Playback Switch",1, 0, 1)) < 0)
288// return ret;
289
290 for (i=0; i < 24; i++)
291 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Volume",vol_6_ch[i], i, 2)) < 0)
292 return ret;
293 for (i=0; i < 24; i++)
294 if ((ret = uniaud_mixer_put_value_by_name(card_id,"EMU10K1 PCM Send Routing",routing_lfe[i], i, 2)) < 0)
295 return ret;
296 }
297
298// if ((ret = uniaud_mixer_put_value_by_name(card_id,"SB Live Analog/Digital Output Jack",0,0,0) < 0)
299// printf("err10\n");
300
301 return ret;
302}
303
304card_type_ids uniaud_get_card_type_id(int card_id)
305{
306 int ret, i;
307 UniaudCardInfo CardInfoL = {0};
308
309 if ((ret = uniaud_get_card_info(card_id, &CardInfoL)) < 0)
310 return ret;
311
312 i = 0;
313 while(card_type_id_table[i].driver != 0)
314 {
315 if (strcmp(card_type_id_table[i].driver,CardInfoL.driver) == 0)
316 return card_type_id_table[i].card_type_id;
317 i++;
318 }
319 return UNIAUD_TYPE_ID_UNKNOWN;
320}
321
322chan_convert_table_t * uniaud_get_card_conv_table(card_type_ids cardt_id)
323{
324 int i;
325
326 i = 0;
327 while(card_type_id_table[i].driver != 0)
328 {
329 if (card_type_id_table[i].card_type_id == cardt_id)
330 return card_type_id_table[i].chan_convert_table;
331 i++;
332 }
333 return NULL;
334}
335
336int uniaud_is_pcm_spdif(int card_id, int pcm_id)
337{
338 int ret, caps;
339 POSS32_DEVCAPS pcaps = NULL;
340 POSS32_DEVCAPS pcaps1 = NULL;
341
342 caps = uniaud_get_pcm_instances(card_id);
343 if (caps <= 0) return -UNIAUD_INVALID_CARD;
344
345 if (pcm_id < 0 || pcm_id > (caps-1)) return -UNIAUD_INVALID_PARAMETER;
346
347 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
348 if (!pcaps) return -UNIAUD_MEMORY_ERROR;
349
350 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0) {
351 free(pcaps);
352 return ret;
353 }
354
355 pcaps1 = pcaps + pcm_id;
356
357 ret = 0;
358 if (!memicmp(pcaps1->szDeviceName, "IEC958", 6)) {
359 ret = 1;
360 }
361 if (pcaps) free(pcaps);
362
363 return ret;
364}
365
366int uniaud_fill_subpcms(int card_id, int *subpcms)
367{
368 int ret, i, caps;
369 card_type_ids cardt = UNIAUD_TYPE_ID_UNKNOWN;
370 POSS32_DEVCAPS pcaps = NULL;
371 POSS32_DEVCAPS pcaps1 = NULL;
372
373 caps = uniaud_get_pcm_instances(card_id);
374 if (caps <= 0)
375 return -UNIAUD_INVALID_CARD;
376
377 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
378 if (!pcaps)
379 return -UNIAUD_MEMORY_ERROR;
380
381 pcaps1 = pcaps;
382
383 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0)
384 return ret;
385
386 cardt = uniaud_get_card_type_id(card_id);
387
388// printf("cp1: %s\n", CardInfoL.driver);
389
390 switch(cardt)
391 {
392 case UNIAUD_TYPE_ID_YMF724:
393 case UNIAUD_TYPE_ID_YMF724F:
394 case UNIAUD_TYPE_ID_YMF740:
395 case UNIAUD_TYPE_ID_YMF740C:
396 case UNIAUD_TYPE_ID_YMF744:
397 case UNIAUD_TYPE_ID_YMF754:
398 case UNIAUD_TYPE_ID_AUDIGYLS:
399 *subpcms = 0;
400 *(subpcms+2) = 0;
401 for (i=0; i<caps;i++)
402 {
403 if (strstr(pcaps->szDeviceName,"Rear") != NULL)
404 {
405 // printf("found rear at %i\n",i);
406 *(subpcms+1) = i;
407 break;
408 }
409 pcaps++;
410 }
411 break;
412 }
413 free(pcaps1);
414 return 0;
415}
416
417int uniaud_get_max_channels(int card_id)
418{
419 int ret, chans, caps;
420 card_type_ids cardt = UNIAUD_TYPE_ID_UNKNOWN;
421 POSS32_DEVCAPS pcaps = NULL;
422
423
424 caps = uniaud_get_pcm_instances(card_id);
425 if (caps <= 0)
426 return -UNIAUD_INVALID_CARD;
427
428 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
429 if (!pcaps)
430 return -UNIAUD_MEMORY_ERROR;
431
432 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0)
433 return ret;
434
435 cardt = uniaud_get_card_type_id(card_id);
436
437// printf("cp1: %s\n", CardInfoL.driver);
438
439 switch(cardt)
440 {
441 case UNIAUD_TYPE_ID_EMU10K1:
442 case UNIAUD_TYPE_ID_AUDIGY:
443 chans = 6;
444 break;
445 case UNIAUD_TYPE_ID_AUDIGY2:
446 chans = 8;
447 break;
448 case UNIAUD_TYPE_ID_YMF724:
449 case UNIAUD_TYPE_ID_YMF724F:
450 case UNIAUD_TYPE_ID_YMF740:
451 case UNIAUD_TYPE_ID_YMF740C:
452 case UNIAUD_TYPE_ID_YMF744:
453 case UNIAUD_TYPE_ID_YMF754:
454 chans = 4;
455 break;
456 case UNIAUD_TYPE_ID_CMI8738:
457 case UNIAUD_TYPE_ID_CMI8338:
458 case UNIAUD_TYPE_ID_CMI:
459 case UNIAUD_TYPE_ID_FM801:
460 chans = uniaud_pcm_find_max_chan(pcaps, caps, 0);
461 break;
462 case UNIAUD_TYPE_ID_UNKNOWN:
463 default:
464 chans = uniaud_pcm_find_max_chan(pcaps, caps, 0);
465 break;
466 }
467 free(pcaps);
468 return chans;
469}
470
471int uniaud_pcm_open_subpcms(int card_id, int type, int *pcm_instance, int access_flag,
472 int sample_rate, int channels, int pcm_format,
473 uniaud_pcm **pcm)
474{
475 int err;
476
477 if (channels <= 2)
478 err = _uniaud_pcm_open(card_id, type, *pcm_instance, access_flag, sample_rate, channels,
479 pcm_format, pcm);
480 else
481 err = _uniaud_pcm_open(card_id, type, *pcm_instance, access_flag, sample_rate, 2,
482 pcm_format, pcm);
483
484 if (!(*pcm) || err != 0)
485 return err;
486
487 if (channels >= 4)
488 {
489 err = _uniaud_pcm_open(card_id, type, *(pcm_instance+1), access_flag, sample_rate, 2,
490 pcm_format, &(*pcm)->pcm_rear);
491 if (!(*pcm)->pcm_rear || err != 0)
492 return err;
493
494 (*pcm)->pcm_rear->multi_buf = malloc((*pcm)->pcm_rear->bufsize);
495 }
496
497 if (channels == 6)
498 {
499 err = _uniaud_pcm_open(card_id, type, *(pcm_instance+2), access_flag, sample_rate, 2,
500 pcm_format, &(*pcm)->pcm_center_lfe);
501 if (!(*pcm)->pcm_center_lfe || err != 0)
502 return err;
503 (*pcm)->pcm_center_lfe->multi_buf = malloc((*pcm)->pcm_center_lfe->bufsize);
504 }
505 return UNIAUD_NO_ERROR;
506}
507
508int uniaud_pcm_open_substreams(int card_id, int type, int pcm_instance, int access_flag,
509 int sample_rate, int channels, int pcm_format,
510 uniaud_pcm **pcm)
511{
512 int err;
513
514 if (channels <= 2)
515 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, channels,
516 pcm_format, pcm);
517 else
518 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, 2,
519 pcm_format, pcm);
520
521 if (!(*pcm) || err != 0)
522 return err;
523
524 if (channels >= 4)
525 {
526 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, 2,
527 pcm_format, &(*pcm)->pcm_rear);
528 if (!(*pcm)->pcm_rear || err != 0)
529 return err;
530
531 (*pcm)->pcm_rear->multi_buf = malloc((*pcm)->pcm_rear->bufsize);
532 }
533 if (channels == 6)
534 {
535 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, 2,
536 pcm_format, &(*pcm)->pcm_center_lfe);
537 if (!(*pcm)->pcm_center_lfe || err != 0)
538 return err;
539 (*pcm)->pcm_center_lfe->multi_buf = malloc((*pcm)->pcm_center_lfe->bufsize);
540 }
541 return UNIAUD_NO_ERROR;
542}
543
544int uniaud_pcm_open_single(int card_id, int type, int pcm_instance, int access_flag,
545 int sample_rate, int channels, int pcm_format,
546 uniaud_pcm **pcm)
547{
548 int err;
549#if 0
550 POSS32_DEVCAPS pcaps = NULL;
551 int ret, caps, chans, pcm_cap;
552 caps = uniaud_get_pcm_instances(card_id);
553 //printf("caps = %i\n", caps);
554 if (caps <= 0)
555 return -UNIAUD_INVALID_CARD;
556
557 pcaps = malloc(sizeof(OSS32_DEVCAPS)*caps);
558 if (!pcaps)
559 return -UNIAUD_MEMORY_ERROR;
560
561 if ((ret = uniaud_pcm_get_caps(card_id, pcaps)) < 0)
562 return ret;
563
564 pcm_cap = uniaud_pcm_find_pcm_for_chan(pcaps, caps, type, channels);
565
566 free(pcaps);
567
568 if (pcm_cap < 0)
569 return -UNIAUD_INVALID_CARD;
570 //printf("found instance %i for %i channels\n", pcm_cap, channels);
571 err = _uniaud_pcm_open(card_id, type, /*pcm_cap*/1, access_flag, sample_rate, channels,
572 pcm_format, pcm);
573#else
574 err = _uniaud_pcm_open(card_id, type, pcm_instance, access_flag, sample_rate, channels,
575 pcm_format, pcm);
576#endif
577 //printf("cp1. err= %i\n", err);
578 if (!(*pcm) || err != 0)
579 return err;
580
581 return UNIAUD_NO_ERROR;
582}
583
584int uniaud_pcm_open(int card_id, int type, int pcm_instance, int access_flag,
585 int sample_rate, int channels, int pcm_format,
586 uniaud_pcm **pcm)
587{
588 card_type_ids cardt_id;
589 int err;
590
591 cardt_id = uniaud_get_card_type_id(card_id);
592 init_fast_memcpy(mm_support());
593 if (uniaud_is_pcm_spdif(card_id, pcm_instance))
594 {
595 err = uniaud_pcm_open_single(card_id, type, pcm_instance, access_flag, sample_rate, channels,
596 pcm_format, pcm);
597 }
598 else
599 {
600 switch(cardt_id)
601 {
602 // case UNIAUD_TYPE_ID_UNKNOWN:
603 // return -UNIAUD_INVALID_CARD;
604 case UNIAUD_TYPE_ID_EMU10K1:
605 err = uniaud_pcm_open_substreams(card_id, type, pcm_instance, access_flag, sample_rate, channels,
606 pcm_format, pcm);
607 if (!err && type == 0)
608 err = uniaud_mixer_sblive_set(card_id, channels);
609 break;
610 case UNIAUD_TYPE_ID_AUDIGY:
611 err = uniaud_pcm_open_substreams(card_id, type, pcm_instance, access_flag, sample_rate, channels,
612 pcm_format, pcm);
613 if (!err && type == 0)
614 err = uniaud_mixer_audigy_set(card_id, channels);
615 break;
616 case UNIAUD_TYPE_ID_AUDIGY2:
617 err = uniaud_pcm_open_substreams(card_id, type, pcm_instance, access_flag, sample_rate, channels,
618 pcm_format, pcm);
619 if (!err && type == 0)
620 err = uniaud_mixer_audigy2_set(card_id, channels);
621 break;
622 case UNIAUD_TYPE_ID_CMI8738:
623 // case UNIAUD_TYPE_ID_CMI8338: need sub pcm support
624 case UNIAUD_TYPE_ID_CMI:
625 {
626 int ch_mode = 1;
627 int instance = pcm_instance;
628 if (channels > 2)
629 {
630 instance = 1;
631 ch_mode = 0;
632 }
633 //printf("opening cmedia: inst: %i, ch: %i: sr: %i\n", instance, channels, sample_rate);
634 err = uniaud_pcm_open_single(card_id, type, instance, access_flag, sample_rate, channels,
635 pcm_format, pcm);
636 uniaud_mixer_put_value_by_name(card_id,"Four Channel Mode",ch_mode, 0, 0);
637 break;
638 }
639 case UNIAUD_TYPE_ID_FM801:
640 err = uniaud_pcm_open_single(card_id, type, pcm_instance, access_flag, sample_rate, channels,
641 pcm_format, pcm);
642 break;
643 case UNIAUD_TYPE_ID_YMF724:
644 case UNIAUD_TYPE_ID_YMF724F:
645 case UNIAUD_TYPE_ID_YMF740:
646 case UNIAUD_TYPE_ID_YMF740C:
647 case UNIAUD_TYPE_ID_YMF744:
648 case UNIAUD_TYPE_ID_YMF754:
649 case UNIAUD_TYPE_ID_AUDIGYLS:
650 {
651 int subpcms[3];
652 if ((err = uniaud_fill_subpcms(card_id, subpcms)) == 0)
653 {
654 err = uniaud_pcm_open_subpcms(card_id, type,
655 subpcms, access_flag,
656 sample_rate, channels,
657 pcm_format, pcm);
658 if (!err)
659 {
660 if (channels > 2)
661 {
662 if (uniaud_mixer_put_value_by_name(card_id,
663 "Shared Rear/Line-In Switch",
664 1, 0, 0) !=0);
665 // printf("error setting line in as rear\n");
666 if (uniaud_mixer_put_value_by_name(card_id,
667 "Surround Playback Switch",
668 1, 0, 0) !=0);
669 if (uniaud_mixer_put_value_by_name(card_id,
670 "Surround Playback Volume",
671 31, 0, 0) !=0);
672 if (uniaud_mixer_put_value_by_name(card_id,
673 "Surround Playback Switch",
674 1, 1, 0) !=0);
675 if (uniaud_mixer_put_value_by_name(card_id,
676 "Surround Playback Volume",
677 31, 1, 0) !=0);
678 }
679 }
680 }
681 }
682 break;
683 case UNIAUD_TYPE_ID_NFORCE:
684 case UNIAUD_TYPE_ID_ICH:
685 case UNIAUD_TYPE_ID_ICH4:
686 case UNIAUD_TYPE_ID_ICH5:
687 {
688 int ch_mode = 0; /* 2 ch */
689
690 switch(channels)
691 {
692 case 4: ch_mode = 1; break;
693 case 6: ch_mode = 2; break;
694 case 8: ch_mode = 3; break;
695 }
696
697 if (uniaud_mixer_put_value_by_name(card_id, "Channel Mode",
698 ch_mode, 0, 0) !=0);
699 err = uniaud_pcm_open_single(card_id, type, pcm_instance,
700 access_flag, sample_rate, channels,
701 pcm_format, pcm);
702 }
703 break;
704 case UNIAUD_TYPE_ID_VIA8233A:
705 case UNIAUD_TYPE_ID_VIA8237:
706 case UNIAUD_TYPE_ID_VIA8233:
707 {
708 int ch_mode = 0; /* 2 ch */
709 int instance = 0;
710
711 switch(channels)
712 {
713 case 4:
714 ch_mode = 1;
715 instance = 1;
716 if (uniaud_mixer_put_value_by_name(card_id, "Surround Down Mix",
717 0, 0, 0) !=0);
718 if (uniaud_mixer_put_value_by_name(card_id, "Swap Surround Slot",
719 0, 0, 0) !=0);
720 break;
721 case 6:
722 ch_mode = 2;
723 instance = 1;
724 if (uniaud_mixer_put_value_by_name(card_id, "Surround Down Mix",
725 0, 0, 0) !=0);
726 if (uniaud_mixer_put_value_by_name(card_id, "Center/LFE Down Mix",
727 0, 0, 0) !=0);
728 if (uniaud_mixer_put_value_by_name(card_id, "Mic As Center/LFE",
729 1, 0, 0) !=0);
730 if (uniaud_mixer_put_value_by_name(card_id, "Swap Surround Slot",
731 1, 0, 0) !=0);
732 break;
733 }
734
735 if (uniaud_mixer_put_value_by_name(card_id, "Channel Mode",
736 ch_mode, 0, 0) !=0);
737 if (cardt_id == UNIAUD_TYPE_ID_VIA8233A)
738 {
739 instance = 0;
740 }
741 //printf("opening pcm %i for card type %i, channels: %i\n", instance, cardt_id, channels);
742 err = uniaud_pcm_open_single(card_id, type, instance,
743 access_flag, sample_rate, channels,
744 pcm_format, pcm);
745
746 }
747 break;
748
749 default:
750 err = uniaud_pcm_open_single(card_id, type, pcm_instance, access_flag, sample_rate, channels,
751 pcm_format, pcm);
752 break;
753 } /* switch */
754 }
755 if (*pcm)
756 {
757 (*pcm)->card_type = cardt_id;
758 if (channels > 2)
759 (*pcm)->multi_channels = channels;
760 }
761 return err;
762}
763
764int uniaud_pcm_prepare(uniaud_pcm *pcm)
765{
766 int err;
767
768 err = _uniaud_pcm_prepare(pcm);
769 if (err < 0) return err;
770
771 if (pcm->pcm_rear)
772 {
773 err = _uniaud_pcm_prepare(pcm->pcm_rear);
774 if (err < 0) return err;
775 }
776 if (pcm->pcm_center_lfe)
777 {
778 err = _uniaud_pcm_prepare(pcm->pcm_center_lfe);
779 if (err < 0) return err;
780 }
781 return err;
782}
783
784int uniaud_pcm_start(uniaud_pcm *pcm)
785{
786 int err;
787
788 err = _uniaud_pcm_start(pcm);
789 if (err < 0) return err;
790
791 if (pcm->pcm_rear)
792 {
793 err = _uniaud_pcm_start(pcm->pcm_rear);
794 if (err < 0) return err;
795 }
796 if (pcm->pcm_center_lfe)
797 {
798 err = _uniaud_pcm_start(pcm->pcm_center_lfe);
799 if (err < 0) return err;
800 }
801 return err;
802}
803
804int uniaud_pcm_drop(uniaud_pcm *pcm)
805{
806 int err;
807
808 err = _uniaud_pcm_drop(pcm);
809 if (err < 0) return err;
810
811 if (pcm->pcm_rear)
812 {
813 err = _uniaud_pcm_drop(pcm->pcm_rear);
814 if (err < 0) return err;
815 }
816 if (pcm->pcm_center_lfe)
817 {
818 err = _uniaud_pcm_drop(pcm->pcm_center_lfe);
819 if (err < 0) return err;
820 }
821 return err;
822}
823
824int uniaud_pcm_pause(uniaud_pcm *pcm)
825{
826 int err;
827
828 err = _uniaud_pcm_pause(pcm);
829 if (err < 0) return err;
830
831 if (pcm->pcm_rear)
832 {
833 err = _uniaud_pcm_pause(pcm->pcm_rear);
834 if (err < 0) return err;
835 }
836 if (pcm->pcm_center_lfe)
837 {
838 err = _uniaud_pcm_pause(pcm->pcm_center_lfe);
839 if (err < 0) return err;
840 }
841 return err;
842}
843
844int uniaud_pcm_resume(uniaud_pcm *pcm)
845{
846 int err;
847
848 err = _uniaud_pcm_resume(pcm);
849 if (err < 0) return err;
850
851 if (pcm->pcm_rear)
852 {
853 err = _uniaud_pcm_resume(pcm->pcm_rear);
854 if (err < 0) return err;
855 }
856 if (pcm->pcm_center_lfe)
857 {
858 err = _uniaud_pcm_resume(pcm->pcm_center_lfe);
859 if (err < 0) return err;
860 }
861 return err;
862}
863
864
865int uniaud_pcm_close(uniaud_pcm *pcm)
866{
867 int err;
868
869 if (pcm && pcm->pcm_center_lfe)
870 {
871 err = _uniaud_pcm_close(pcm->pcm_center_lfe);
872 //if (err < 0) return err;
873 }
874 if (pcm && pcm->pcm_rear)
875 {
876 err = _uniaud_pcm_close(pcm->pcm_rear);
877 //if (err < 0) return err;
878 }
879
880 err = _uniaud_pcm_close(pcm);
881
882 return err;
883}
884
885int uniaud_pcm_wait(uniaud_pcm *pcm, int timeout)
886{
887 int err = 0;
888#if 0
889 if (pcm->pcm_center_lfe)
890 {
891 err = _uniaud_pcm_wait(pcm->pcm_center_lfe, timeout);
892 if (err < 0) return err;
893 } else
894 if (pcm->pcm_rear)
895 {
896 err = _uniaud_pcm_wait(pcm->pcm_rear, timeout);
897 if (err < 0) return err;
898 }
899 else
900#endif
901 //printf("tout = %i %x %x\n", timeout, pcm->pcm_center_lfe, pcm->pcm_rear);
902
903 //if (!pcm->pcm_center_lfe &&
904 // !pcm->pcm_rear)
905 err = _uniaud_pcm_wait(pcm, timeout);
906
907 return err;
908}
909
910static inline uint16_t bswap_16(uint16_t x){
911 return (x>>8) | (x<<8);
912}
913
914
915int16_t swapBuf[8*3] __attribute__((aligned(16))) = {0}; /*up to 24 bit samples to 8 channels */
916int last_ret = 0;
917
918int uniaud_pcm_write(uniaud_pcm *pcm, char *Buffer, int size)
919{
920 int err = 0;
921 int err1 = 0, err2 = 0, err3 = 0;
922 int ret = 0;
923 int ret1 = 0, ret2 = 0, ret3 = 0;
924 int i, j, state;
925 int written = 0;
926 //int written1 = 0;
927 int written_front = 0, written_rear = 0, written_lfe = 0;
928 chan_convert_table_t *ct = NULL;
929 //FILE *f;
930 int16_t *b = (int16_t *)Buffer;
931 //int16_t sample;
932
933 int samplesize = uniaud_pcm_format_size(pcm->format, 1);
934
935 //printf("ss=%i, ch: %i\n", samplesize, pcm->multi_channels);
936 if (!Buffer || size <= 0)
937 return -UNIAUD_MEMORY_ERROR;
938
939 ct = uniaud_get_card_conv_table(pcm->card_type);
940 if (last_ret == 0) last_ret = /*size*/pcm->period_size;
941 //printf("ss=%i, ch: %i, ct: %x, lr: %i\n", samplesize, pcm->multi_channels, ct, last_ret);
942 if (ct && pcm->multi_channels >= 4 && last_ret > 0)
943 {
944 //for (j=0; j < pcm->multi_channels; j++)
945 // printf("%i -> %i\n", ct->src[j], ct->dst[j]);
946 if (size < last_ret) last_ret = size;
947 //printf("lastret: %i\n", last_ret);
948 for(i=0; i < last_ret/samplesize; i+=pcm->multi_channels/**samplesize*/)
949 {
950 memset(&swapBuf[0], 0, sizeof(swapBuf));
951 for (j=0; j < pcm->multi_channels; j++)
952 swapBuf[j] = b[i+j];
953 for (j=0; j < pcm->multi_channels; j++)
954 b[i+ct->dst[j]] = swapBuf[ct->src[j]];
955
956 }
957 }
958
959 if ((!pcm->pcm_center_lfe && !pcm->pcm_rear) ||
960 pcm->multi_channels <= 2)
961 { // single PCM multichannel or 2 or less channels write
962 //again:
963 ret = _uniaud_pcm_write(pcm, Buffer, size);
964 //printf("ret = %i, size: <%i>\n", ret, size);
965 if (ret == -77)
966 {
967 //_uniaud_pcm_reinit(pcm);
968 //goto again;
969 }
970 if (ret>0)
971 last_ret = ret;
972 return ret;
973 }
974 if (!pcm->multi_buf)
975 return -UNIAUD_MEMORY_ERROR;
976
977// if ((size % (samplesize*pcm->multi_channels)) != 0)
978// printf("size is not aligned to number of channels\n");
979
980// printf("%i, %i, %i\n",samplesize, pcm->multi_channels, pcm->format);
981
982 j=0;
983 if (1)
984 {
985 for (i=0; i<size;i+=samplesize*pcm->multi_channels)
986 {
987#if 1
988 memcpy(pcm->multi_buf+j, Buffer+i, 4);
989 if (pcm->pcm_center_lfe)
990 {
991 memcpy(pcm->multi_buf+j, Buffer+i+4, 4);
992 }
993 if (pcm->pcm_rear)
994 {
995 memcpy(pcm->multi_buf+j, Buffer+i+8, 4);
996 }
997#else
998 unsigned int *bufPtrIn;
999 unsigned int *bufPtrOut;
1000
1001 bufPtrIn = (unsigned int*)pcm->multi_buf;
1002 bufPtrOut = (unsigned int*)Buffer;
1003 bufPtrIn[j/4] = bufPtrOut[i/4];
1004#if 0
1005 (unsigned int)*(unsigned int*)(pcm->multi_buf+j) =
1006 (unsigned int)*(unsigned int*)(Buffer+i);
1007 if (pcm->pcm_center_lfe)
1008 {
1009 (unsigned int)*(unsigned int*)(pcm->pcm_center_lfe->multi_buf+j) =
1010 (unsigned int)*(unsigned int*)(Buffer+i+4);
1011 }
1012 if (pcm->pcm_rear)
1013 {
1014 (unsigned int)*(unsigned int*)(pcm->pcm_rear->multi_buf+j) =
1015 (unsigned int)*(unsigned int*)(Buffer+i+8);
1016 }
1017#endif
1018#endif
1019 j+=samplesize*2;
1020 }
1021 } /* !cf */
1022 {
1023#if 0
1024 FILE *f;
1025 f = fopen("uniaudm.dmp","ab");
1026 fwrite(pcm->pcm_center_lfe->multi_buf, j,1,f);
1027 fclose(f);
1028
1029#endif
1030 }
1031 while (written < size)
1032 {
1033 err1 = err2 = err3 = 0;
1034 ret1 = ret2 = ret3 = 0;
1035
1036 err3 = _uniaud_pcm_write(pcm, pcm->multi_buf+written_front, j-written_front);
1037
1038 if (pcm->pcm_rear)
1039 err1 = _uniaud_pcm_write(pcm->pcm_rear, pcm->pcm_rear->multi_buf+written_rear, j-written_rear);
1040
1041 if (pcm->pcm_center_lfe)
1042 err2 = _uniaud_pcm_write(pcm->pcm_center_lfe, pcm->pcm_center_lfe->multi_buf+written_lfe, j-written_lfe);
1043
1044
1045#if 0
1046 if (err1 > 0)
1047 ret1 = _uniaud_pcm_wait(pcm->pcm_rear, 1000);
1048 else if (err2 > 0)
1049 ret2 = _uniaud_pcm_wait(pcm->pcm_center_lfe, 1000);
1050 else
1051#endif
1052 // if (err3 > 0)
1053 ret3 = _uniaud_pcm_wait(pcm, 1000);
1054
1055 if (err1 > 0)
1056 {
1057 written+=err1;
1058 written_rear+=err1;
1059 }
1060 if (err2 > 0)
1061 {
1062 written+=err2;
1063 written_lfe+=err2;
1064 }
1065 if (err3 > 0)
1066 {
1067 written+=err3;
1068 written_front+=err3;
1069 }
1070
1071 if (err1 < 0 && err1 != -EAGAIN)
1072 {
1073 //if (err1 == -77)
1074 // _uniaud_pcm_reinit(pcm);
1075 state = uniaud_pcm_state(pcm->pcm_rear);
1076 if ( (state != SND_PCM_STATE_PREPARED) &&
1077 (state != SND_PCM_STATE_RUNNING) &&
1078 (state != SND_PCM_STATE_DRAINING) ) {
1079 if ((ret1 = _uniaud_pcm_prepare(pcm->pcm_rear))<0)
1080 break;
1081 }
1082// printf("err writing %i bytes to rear from %i, err: %i\n",written_rear,j,err1);
1083 }
1084
1085 if (err2 < 0 && err2 != -EAGAIN)
1086 {
1087 //if (err2 == -77)
1088 // _uniaud_pcm_reinit(pcm);
1089 state = uniaud_pcm_state(pcm->pcm_center_lfe);
1090 if ( (state != SND_PCM_STATE_PREPARED) &&
1091 (state != SND_PCM_STATE_RUNNING) &&
1092 (state != SND_PCM_STATE_DRAINING) ) {
1093 if ((ret2 = _uniaud_pcm_prepare(pcm->pcm_center_lfe))<0)
1094 break;
1095 }
1096// printf("err writing %i bytes to center/lfe from %i, err: %i\n",written_lfe,j,err2);
1097 }
1098
1099 if (err3 < 0 && err3 != -EAGAIN)
1100 {
1101 //if (err3 == -77)
1102 // _uniaud_pcm_reinit(pcm);
1103 state = uniaud_pcm_state(pcm);
1104 if ( (state != SND_PCM_STATE_PREPARED) &&
1105 (state != SND_PCM_STATE_RUNNING) &&
1106 (state != SND_PCM_STATE_DRAINING) ) {
1107 if ((ret3 = _uniaud_pcm_prepare(pcm))<0)
1108 break;
1109 }
1110// printf("err writing %i bytes to front from %i, err: %i\n",written_front,j,err3);
1111 }
1112 }
1113
1114// printf("wr: %i\n", j);
1115 if (written > 0)
1116 return written;
1117 return err;
1118}
1119
Note: See TracBrowser for help on using the repository browser.