|
|
1.1 root 1: /*
1.1.1.2 root 2: * QEMU FMOD audio driver
3: *
4: * Copyright (c) 2004-2005 Vassili Karpov (malc)
5: *
1.1 root 6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
24: #include <fmod.h>
25: #include <fmod_errors.h>
1.1.1.4 ! root 26: #include "qemu-common.h"
! 27: #include "audio.h"
1.1 root 28:
1.1.1.2 root 29: #define AUDIO_CAP "fmod"
30: #include "audio_int.h"
1.1 root 31:
1.1.1.2 root 32: typedef struct FMODVoiceOut {
33: HWVoiceOut hw;
1.1 root 34: unsigned int old_pos;
35: FSOUND_SAMPLE *fmod_sample;
36: int channel;
1.1.1.2 root 37: } FMODVoiceOut;
1.1 root 38:
1.1.1.2 root 39: typedef struct FMODVoiceIn {
40: HWVoiceIn hw;
41: FSOUND_SAMPLE *fmod_sample;
42: } FMODVoiceIn;
1.1 root 43:
44: static struct {
1.1.1.2 root 45: const char *drvname;
1.1 root 46: int nb_samples;
47: int freq;
48: int nb_channels;
49: int bufsize;
50: int threshold;
1.1.1.2 root 51: int broken_adc;
1.1 root 52: } conf = {
1.1.1.2 root 53: NULL,
54: 2048 * 2,
1.1 root 55: 44100,
1.1.1.2 root 56: 2,
57: 0,
1.1 root 58: 0,
1.1.1.2 root 59: 0
1.1 root 60: };
61:
1.1.1.2 root 62: static void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...)
63: {
64: va_list ap;
65:
66: va_start (ap, fmt);
67: AUD_vlog (AUDIO_CAP, fmt, ap);
68: va_end (ap);
1.1 root 69:
1.1.1.2 root 70: AUD_log (AUDIO_CAP, "Reason: %s\n",
71: FMOD_ErrorString (FSOUND_GetError ()));
72: }
73:
74: static void GCC_FMT_ATTR (2, 3) fmod_logerr2 (
75: const char *typ,
76: const char *fmt,
77: ...
78: )
1.1 root 79: {
1.1.1.2 root 80: va_list ap;
81:
82: AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
83:
84: va_start (ap, fmt);
85: AUD_vlog (AUDIO_CAP, fmt, ap);
86: va_end (ap);
87:
88: AUD_log (AUDIO_CAP, "Reason: %s\n",
89: FMOD_ErrorString (FSOUND_GetError ()));
1.1 root 90: }
91:
1.1.1.2 root 92: static int fmod_write (SWVoiceOut *sw, void *buf, int len)
1.1 root 93: {
1.1.1.2 root 94: return audio_pcm_sw_write (sw, buf, len);
95: }
96:
97: static void fmod_clear_sample (FMODVoiceOut *fmd)
98: {
99: HWVoiceOut *hw = &fmd->hw;
1.1 root 100: int status;
101: void *p1 = 0, *p2 = 0;
102: unsigned int len1 = 0, len2 = 0;
103:
104: status = FSOUND_Sample_Lock (
105: fmd->fmod_sample,
106: 0,
1.1.1.2 root 107: hw->samples << hw->info.shift,
1.1 root 108: &p1,
109: &p2,
110: &len1,
111: &len2
112: );
113:
114: if (!status) {
1.1.1.2 root 115: fmod_logerr ("Failed to lock sample\n");
1.1 root 116: return;
117: }
118:
1.1.1.2 root 119: if ((len1 & hw->info.align) || (len2 & hw->info.align)) {
120: dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
121: len1, len2, hw->info.align + 1);
1.1 root 122: goto fail;
123: }
124:
1.1.1.2 root 125: if ((len1 + len2) - (hw->samples << hw->info.shift)) {
126: dolog ("Lock returned incomplete length %d, %d\n",
127: len1 + len2, hw->samples << hw->info.shift);
1.1 root 128: goto fail;
129: }
1.1.1.2 root 130:
131: audio_pcm_info_clear_buf (&hw->info, p1, hw->samples);
1.1 root 132:
133: fail:
134: status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
135: if (!status) {
1.1.1.2 root 136: fmod_logerr ("Failed to unlock sample\n");
1.1 root 137: }
138: }
139:
1.1.1.2 root 140: static void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
1.1 root 141: {
1.1.1.2 root 142: int src_len1 = dst_len;
143: int src_len2 = 0;
144: int pos = hw->rpos + dst_len;
145: st_sample_t *src1 = hw->mix_buf + hw->rpos;
146: st_sample_t *src2 = NULL;
1.1 root 147:
1.1.1.2 root 148: if (pos > hw->samples) {
149: src_len1 = hw->samples - hw->rpos;
150: src2 = hw->mix_buf;
1.1 root 151: src_len2 = dst_len - src_len1;
152: pos = src_len2;
153: }
154:
155: if (src_len1) {
156: hw->clip (dst, src1, src_len1);
157: }
158:
159: if (src_len2) {
1.1.1.2 root 160: dst = advance (dst, src_len1 << hw->info.shift);
1.1 root 161: hw->clip (dst, src2, src_len2);
162: }
1.1.1.2 root 163:
164: hw->rpos = pos % hw->samples;
1.1 root 165: }
166:
1.1.1.2 root 167: static int fmod_unlock_sample (FSOUND_SAMPLE *sample, void *p1, void *p2,
1.1 root 168: unsigned int blen1, unsigned int blen2)
169: {
1.1.1.2 root 170: int status = FSOUND_Sample_Unlock (sample, p1, p2, blen1, blen2);
1.1 root 171: if (!status) {
1.1.1.2 root 172: fmod_logerr ("Failed to unlock sample\n");
1.1 root 173: return -1;
174: }
175: return 0;
176: }
177:
1.1.1.2 root 178: static int fmod_lock_sample (
179: FSOUND_SAMPLE *sample,
180: struct audio_pcm_info *info,
181: int pos,
182: int len,
183: void **p1,
184: void **p2,
185: unsigned int *blen1,
186: unsigned int *blen2
187: )
1.1 root 188: {
189: int status;
190:
191: status = FSOUND_Sample_Lock (
1.1.1.2 root 192: sample,
193: pos << info->shift,
194: len << info->shift,
1.1 root 195: p1,
196: p2,
197: blen1,
198: blen2
199: );
200:
201: if (!status) {
1.1.1.2 root 202: fmod_logerr ("Failed to lock sample\n");
1.1 root 203: return -1;
204: }
205:
1.1.1.2 root 206: if ((*blen1 & info->align) || (*blen2 & info->align)) {
207: dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
208: *blen1, *blen2, info->align + 1);
209:
210: fmod_unlock_sample (sample, *p1, *p2, *blen1, *blen2);
211:
212: *p1 = NULL - 1;
213: *p2 = NULL - 1;
214: *blen1 = ~0U;
215: *blen2 = ~0U;
1.1 root 216: return -1;
217: }
1.1.1.2 root 218:
219: if (!*p1 && *blen1) {
220: dolog ("warning: !p1 && blen1=%d\n", *blen1);
221: *blen1 = 0;
222: }
223:
224: if (!p2 && *blen2) {
225: dolog ("warning: !p2 && blen2=%d\n", *blen2);
226: *blen2 = 0;
227: }
228:
1.1 root 229: return 0;
230: }
231:
1.1.1.2 root 232: static int fmod_run_out (HWVoiceOut *hw)
1.1 root 233: {
1.1.1.2 root 234: FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
235: int live, decr;
1.1 root 236: void *p1 = 0, *p2 = 0;
237: unsigned int blen1 = 0, blen2 = 0;
238: unsigned int len1 = 0, len2 = 0;
1.1.1.2 root 239: int nb_live;
1.1 root 240:
1.1.1.2 root 241: live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
242: if (!live) {
243: return 0;
1.1 root 244: }
245:
246: if (!hw->pending_disable
1.1.1.2 root 247: && nb_live
248: && (conf.threshold && live <= conf.threshold)) {
249: ldebug ("live=%d nb_live=%d\n", live, nb_live);
250: return 0;
1.1 root 251: }
252:
253: decr = live;
254:
255: if (fmd->channel >= 0) {
1.1.1.2 root 256: int len = decr;
257: int old_pos = fmd->old_pos;
258: int ppos = FSOUND_GetCurrentPosition (fmd->channel);
1.1 root 259:
1.1.1.2 root 260: if (ppos == old_pos || !ppos) {
261: return 0;
1.1 root 262: }
1.1.1.2 root 263:
264: if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
265: len = ppos - old_pos;
266: }
267: else {
268: if ((old_pos > ppos) && ((old_pos + len) > (ppos + hw->samples))) {
269: len = hw->samples - old_pos + ppos;
270: }
271: }
272: decr = len;
273:
274: if (audio_bug (AUDIO_FUNC, decr < 0)) {
275: dolog ("decr=%d live=%d ppos=%d old_pos=%d len=%d\n",
276: decr, live, ppos, old_pos, len);
277: return 0;
1.1 root 278: }
279: }
280:
1.1.1.2 root 281:
282: if (!decr) {
283: return 0;
1.1 root 284: }
285:
1.1.1.2 root 286: if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
287: fmd->old_pos, decr,
288: &p1, &p2,
289: &blen1, &blen2)) {
290: return 0;
1.1 root 291: }
292:
1.1.1.2 root 293: len1 = blen1 >> hw->info.shift;
294: len2 = blen2 >> hw->info.shift;
1.1 root 295: ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
296: decr = len1 + len2;
297:
1.1.1.2 root 298: if (p1 && len1) {
299: fmod_write_sample (hw, p1, len1);
1.1 root 300: }
301:
1.1.1.2 root 302: if (p2 && len2) {
303: fmod_write_sample (hw, p2, len2);
1.1 root 304: }
305:
1.1.1.2 root 306: fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
1.1 root 307:
308: fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
1.1.1.2 root 309: return decr;
1.1 root 310: }
311:
1.1.1.2 root 312: static int aud_to_fmodfmt (audfmt_e fmt, int stereo)
1.1 root 313: {
314: int mode = FSOUND_LOOP_NORMAL;
315:
316: switch (fmt) {
317: case AUD_FMT_S8:
318: mode |= FSOUND_SIGNED | FSOUND_8BITS;
319: break;
320:
321: case AUD_FMT_U8:
322: mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
323: break;
324:
325: case AUD_FMT_S16:
326: mode |= FSOUND_SIGNED | FSOUND_16BITS;
327: break;
328:
329: case AUD_FMT_U16:
330: mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
331: break;
332:
333: default:
1.1.1.2 root 334: dolog ("Internal logic error: Bad audio format %d\n", fmt);
335: #ifdef DEBUG_FMOD
336: abort ();
337: #endif
338: mode |= FSOUND_8BITS;
1.1 root 339: }
340: mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
341: return mode;
342: }
343:
1.1.1.2 root 344: static void fmod_fini_out (HWVoiceOut *hw)
1.1 root 345: {
1.1.1.2 root 346: FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
1.1 root 347:
348: if (fmd->fmod_sample) {
349: FSOUND_Sample_Free (fmd->fmod_sample);
350: fmd->fmod_sample = 0;
351:
352: if (fmd->channel >= 0) {
353: FSOUND_StopSound (fmd->channel);
354: }
355: }
356: }
357:
1.1.1.2 root 358: static int fmod_init_out (HWVoiceOut *hw, audsettings_t *as)
1.1 root 359: {
360: int bits16, mode, channel;
1.1.1.2 root 361: FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
1.1.1.3 root 362: audsettings_t obt_as = *as;
1.1 root 363:
1.1.1.2 root 364: mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
1.1 root 365: fmd->fmod_sample = FSOUND_Sample_Alloc (
366: FSOUND_FREE, /* index */
367: conf.nb_samples, /* length */
368: mode, /* mode */
1.1.1.2 root 369: as->freq, /* freq */
1.1 root 370: 255, /* volume */
371: 128, /* pan */
372: 255 /* priority */
373: );
374:
375: if (!fmd->fmod_sample) {
1.1.1.2 root 376: fmod_logerr2 ("DAC", "Failed to allocate FMOD sample\n");
1.1 root 377: return -1;
378: }
379:
380: channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1);
381: if (channel < 0) {
1.1.1.2 root 382: fmod_logerr2 ("DAC", "Failed to start playing sound\n");
1.1 root 383: FSOUND_Sample_Free (fmd->fmod_sample);
384: return -1;
385: }
386: fmd->channel = channel;
387:
1.1.1.2 root 388: /* FMOD always operates on little endian frames? */
1.1.1.3 root 389: obt_as.endianness = 0;
390: audio_pcm_init_info (&hw->info, &obt_as);
1.1.1.2 root 391: bits16 = (mode & FSOUND_16BITS) != 0;
392: hw->samples = conf.nb_samples;
1.1 root 393: return 0;
394: }
395:
1.1.1.2 root 396: static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...)
1.1 root 397: {
398: int status;
1.1.1.2 root 399: FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
1.1 root 400:
401: switch (cmd) {
402: case VOICE_ENABLE:
403: fmod_clear_sample (fmd);
404: status = FSOUND_SetPaused (fmd->channel, 0);
405: if (!status) {
1.1.1.2 root 406: fmod_logerr ("Failed to resume channel %d\n", fmd->channel);
1.1 root 407: }
408: break;
409:
410: case VOICE_DISABLE:
411: status = FSOUND_SetPaused (fmd->channel, 1);
412: if (!status) {
1.1.1.2 root 413: fmod_logerr ("Failed to pause channel %d\n", fmd->channel);
1.1 root 414: }
415: break;
416: }
417: return 0;
418: }
419:
1.1.1.2 root 420: static int fmod_init_in (HWVoiceIn *hw, audsettings_t *as)
421: {
422: int bits16, mode;
423: FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
1.1.1.3 root 424: audsettings_t obt_as = *as;
1.1.1.2 root 425:
426: if (conf.broken_adc) {
427: return -1;
428: }
429:
430: mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
431: fmd->fmod_sample = FSOUND_Sample_Alloc (
432: FSOUND_FREE, /* index */
433: conf.nb_samples, /* length */
434: mode, /* mode */
435: as->freq, /* freq */
436: 255, /* volume */
437: 128, /* pan */
438: 255 /* priority */
439: );
440:
441: if (!fmd->fmod_sample) {
442: fmod_logerr2 ("ADC", "Failed to allocate FMOD sample\n");
443: return -1;
444: }
445:
446: /* FMOD always operates on little endian frames? */
1.1.1.3 root 447: obt_as.endianness = 0;
448: audio_pcm_init_info (&hw->info, &obt_as);
1.1.1.2 root 449: bits16 = (mode & FSOUND_16BITS) != 0;
450: hw->samples = conf.nb_samples;
451: return 0;
452: }
453:
454: static void fmod_fini_in (HWVoiceIn *hw)
455: {
456: FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
457:
458: if (fmd->fmod_sample) {
459: FSOUND_Record_Stop ();
460: FSOUND_Sample_Free (fmd->fmod_sample);
461: fmd->fmod_sample = 0;
462: }
463: }
464:
465: static int fmod_run_in (HWVoiceIn *hw)
466: {
467: FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
468: int hwshift = hw->info.shift;
469: int live, dead, new_pos, len;
470: unsigned int blen1 = 0, blen2 = 0;
471: unsigned int len1, len2;
472: unsigned int decr;
473: void *p1, *p2;
474:
475: live = audio_pcm_hw_get_live_in (hw);
476: dead = hw->samples - live;
477: if (!dead) {
478: return 0;
479: }
480:
481: new_pos = FSOUND_Record_GetPosition ();
482: if (new_pos < 0) {
483: fmod_logerr ("Could not get recording position\n");
484: return 0;
485: }
486:
487: len = audio_ring_dist (new_pos, hw->wpos, hw->samples);
488: if (!len) {
489: return 0;
490: }
491: len = audio_MIN (len, dead);
492:
493: if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
494: hw->wpos, len,
495: &p1, &p2,
496: &blen1, &blen2)) {
497: return 0;
498: }
499:
500: len1 = blen1 >> hwshift;
501: len2 = blen2 >> hwshift;
502: decr = len1 + len2;
503:
504: if (p1 && blen1) {
505: hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
506: }
507: if (p2 && len2) {
508: hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
509: }
510:
511: fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
512: hw->wpos = (hw->wpos + decr) % hw->samples;
513: return decr;
514: }
515:
1.1 root 516: static struct {
517: const char *name;
518: int type;
519: } drvtab[] = {
520: {"none", FSOUND_OUTPUT_NOSOUND},
521: #ifdef _WIN32
522: {"winmm", FSOUND_OUTPUT_WINMM},
523: {"dsound", FSOUND_OUTPUT_DSOUND},
524: {"a3d", FSOUND_OUTPUT_A3D},
525: {"asio", FSOUND_OUTPUT_ASIO},
526: #endif
527: #ifdef __linux__
528: {"oss", FSOUND_OUTPUT_OSS},
529: {"alsa", FSOUND_OUTPUT_ALSA},
530: {"esd", FSOUND_OUTPUT_ESD},
531: #endif
532: #ifdef __APPLE__
533: {"mac", FSOUND_OUTPUT_MAC},
534: #endif
535: #if 0
536: {"xbox", FSOUND_OUTPUT_XBOX},
537: {"ps2", FSOUND_OUTPUT_PS2},
538: {"gcube", FSOUND_OUTPUT_GC},
539: #endif
1.1.1.2 root 540: {"none-realtime", FSOUND_OUTPUT_NOSOUND_NONREALTIME}
1.1 root 541: };
542:
543: static void *fmod_audio_init (void)
544: {
1.1.1.2 root 545: size_t i;
1.1 root 546: double ver;
547: int status;
548: int output_type = -1;
1.1.1.2 root 549: const char *drv = conf.drvname;
1.1 root 550:
551: ver = FSOUND_GetVersion ();
552: if (ver < FMOD_VERSION) {
553: dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION);
554: return NULL;
555: }
556:
1.1.1.2 root 557: #ifdef __linux__
558: if (ver < 3.75) {
559: dolog ("FMOD before 3.75 has bug preventing ADC from working\n"
560: "ADC will be disabled.\n");
561: conf.broken_adc = 1;
562: }
563: #endif
564:
1.1 root 565: if (drv) {
566: int found = 0;
567: for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
568: if (!strcmp (drv, drvtab[i].name)) {
569: output_type = drvtab[i].type;
570: found = 1;
571: break;
572: }
573: }
574: if (!found) {
1.1.1.2 root 575: dolog ("Unknown FMOD driver `%s'\n", drv);
576: dolog ("Valid drivers:\n");
577: for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
578: dolog (" %s\n", drvtab[i].name);
579: }
1.1 root 580: }
581: }
582:
583: if (output_type != -1) {
584: status = FSOUND_SetOutput (output_type);
585: if (!status) {
1.1.1.2 root 586: fmod_logerr ("FSOUND_SetOutput(%d) failed\n", output_type);
1.1 root 587: return NULL;
588: }
589: }
590:
591: if (conf.bufsize) {
592: status = FSOUND_SetBufferSize (conf.bufsize);
593: if (!status) {
1.1.1.2 root 594: fmod_logerr ("FSOUND_SetBufferSize (%d) failed\n", conf.bufsize);
1.1 root 595: }
596: }
597:
598: status = FSOUND_Init (conf.freq, conf.nb_channels, 0);
599: if (!status) {
1.1.1.2 root 600: fmod_logerr ("FSOUND_Init failed\n");
1.1 root 601: return NULL;
602: }
603:
604: return &conf;
605: }
606:
1.1.1.2 root 607: static int fmod_read (SWVoiceIn *sw, void *buf, int size)
608: {
609: return audio_pcm_sw_read (sw, buf, size);
610: }
611:
612: static int fmod_ctl_in (HWVoiceIn *hw, int cmd, ...)
613: {
614: int status;
615: FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
616:
617: switch (cmd) {
618: case VOICE_ENABLE:
619: status = FSOUND_Record_StartSample (fmd->fmod_sample, 1);
620: if (!status) {
621: fmod_logerr ("Failed to start recording\n");
622: }
623: break;
624:
625: case VOICE_DISABLE:
626: status = FSOUND_Record_Stop ();
627: if (!status) {
628: fmod_logerr ("Failed to stop recording\n");
629: }
630: break;
631: }
632: return 0;
633: }
634:
1.1 root 635: static void fmod_audio_fini (void *opaque)
636: {
1.1.1.2 root 637: (void) opaque;
1.1 root 638: FSOUND_Close ();
639: }
640:
1.1.1.2 root 641: static struct audio_option fmod_options[] = {
642: {"DRV", AUD_OPT_STR, &conf.drvname,
643: "FMOD driver", NULL, 0},
644: {"FREQ", AUD_OPT_INT, &conf.freq,
645: "Default frequency", NULL, 0},
646: {"SAMPLES", AUD_OPT_INT, &conf.nb_samples,
647: "Buffer size in samples", NULL, 0},
648: {"CHANNELS", AUD_OPT_INT, &conf.nb_channels,
649: "Number of default channels (1 - mono, 2 - stereo)", NULL, 0},
650: {"BUFSIZE", AUD_OPT_INT, &conf.bufsize,
651: "(undocumented)", NULL, 0},
652: #if 0
653: {"THRESHOLD", AUD_OPT_INT, &conf.threshold,
654: "(undocumented)"},
655: #endif
656:
657: {NULL, 0, NULL, NULL, NULL, 0}
658: };
659:
660: static struct audio_pcm_ops fmod_pcm_ops = {
661: fmod_init_out,
662: fmod_fini_out,
663: fmod_run_out,
664: fmod_write,
665: fmod_ctl_out,
666:
667: fmod_init_in,
668: fmod_fini_in,
669: fmod_run_in,
670: fmod_read,
671: fmod_ctl_in
1.1 root 672: };
673:
1.1.1.2 root 674: struct audio_driver fmod_audio_driver = {
675: INIT_FIELD (name = ) "fmod",
676: INIT_FIELD (descr = ) "FMOD 3.xx http://www.fmod.org",
677: INIT_FIELD (options = ) fmod_options,
678: INIT_FIELD (init = ) fmod_audio_init,
679: INIT_FIELD (fini = ) fmod_audio_fini,
680: INIT_FIELD (pcm_ops = ) &fmod_pcm_ops,
681: INIT_FIELD (can_be_default = ) 1,
682: INIT_FIELD (max_voices_out = ) INT_MAX,
683: INIT_FIELD (max_voices_in = ) INT_MAX,
684: INIT_FIELD (voice_size_out = ) sizeof (FMODVoiceOut),
685: INIT_FIELD (voice_size_in = ) sizeof (FMODVoiceIn)
1.1 root 686: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.