Revision 85571bc7

b/Makefile.target
1 1
include config.mak
2 2

  
3
#After enabling Adlib and/or FMOD rebuild QEMU from scratch
4
#Uncomment following for adlib support
5
#USE_ADLIB=1
6

  
7
#Uncomment following and specify proper paths/names for FMOD support
8
#USE_FMOD=1
9
#FMOD_INCLUDE=/net/include/fmod
10
#FMOD_LIBPATH=/net/lib
11
#FMOD_VERSION=3.74
12

  
3 13
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
4
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw
14
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
5 15
DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH)
6 16
ifdef CONFIG_USER_ONLY
7 17
VPATH+=:$(SRC_PATH)/linux-user
......
267 277
VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o 
268 278
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
269 279

  
280
SOUND_HW = sb16.o
281
AUDIODRV = audio.o ossaudio.o sdlaudio.o wavaudio.o
282

  
283
ifeq ($(USE_ADLIB),1)
284
SOUND_HW += fmopl.o adlib.o
285
audio.o: DEFINES := -DUSE_ADLIB $(DEFINES)
286
endif
287

  
288
ifeq ($(USE_FMOD),1)
289
AUDIODRV += fmodaudio.o
290
audio.o fmodaudio.o: DEFINES := -DUSE_FMOD_AUDIO -I$(FMOD_INCLUDE) $(DEFINES)
291
LDFLAGS += -L$(FMOD_LIBPATH) -Wl,-rpath,$(FMOD_LIBPATH)
292
LIBS += -lfmod-$(FMOD_VERSION)
293
endif
294

  
270 295
ifeq ($(TARGET_ARCH), i386)
271 296
# Hardware support
272
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
273
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o 
274
VL_OBJS+= cirrus_vga.o
297
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
298
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
299
VL_OBJS+= cirrus_vga.o mixeng.o
275 300
endif
276 301
ifeq ($(TARGET_ARCH), ppc)
277
VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
302
VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
278 303
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
279
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o
304
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o
280 305
endif
281 306
ifeq ($(TARGET_ARCH), sparc)
282 307
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
......
360 385
op_helper.o: op_helper_mem.h
361 386
endif
362 387

  
388
mixeng.o: mixeng.c mixeng.h mixeng_template.h
389

  
363 390
%.o: %.c
364 391
	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
365 392

  
b/audio/audio.c
1
/*
2
 * QEMU Audio subsystem
3
 * 
4
 * Copyright (c) 2003-2004 Vassili Karpov (malc)
5
 * 
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 <assert.h>
25
#include <limits.h>
26
#include "vl.h"
27

  
28
#define AUDIO_CAP "audio"
29
#include "audio/audio.h"
30

  
31
#define USE_SDL_AUDIO
32
#define USE_WAV_AUDIO
33

  
34
#if defined __linux__ || (defined _BSD && !defined __APPLE__)
35
#define USE_OSS_AUDIO
36
#endif
37

  
38
#ifdef USE_OSS_AUDIO
39
#include "audio/ossaudio.h"
40
#endif
41

  
42
#ifdef USE_SDL_AUDIO
43
#include "audio/sdlaudio.h"
44
#endif
45

  
46
#ifdef USE_WAV_AUDIO
47
#include "audio/wavaudio.h"
48
#endif
49

  
50
#ifdef USE_FMOD_AUDIO
51
#include "audio/fmodaudio.h"
52
#endif
53

  
54
#define QC_AUDIO_DRV    "QEMU_AUDIO_DRV"
55
#define QC_VOICES    "QEMU_VOICES"
56
#define QC_FIXED_FORMAT "QEMU_FIXED_FORMAT"
57
#define QC_FIXED_FREQ   "QEMU_FIXED_FREQ"
58

  
59
extern void SB16_init (void);
60

  
61
#ifdef USE_ADLIB
62
extern void Adlib_init (void);
63
#endif
64

  
65
#ifdef USE_GUS
66
extern void GUS_init (void);
67
#endif
68

  
69
static void (*hw_ctors[]) (void) = {
70
    SB16_init,
71
#ifdef USE_ADLIB
72
    Adlib_init,
73
#endif
74
#ifdef USE_GUS
75
    GUS_init,
76
#endif
77
    NULL
78
};
79

  
80
static HWVoice *hw_voice;
81

  
82
AudioState audio_state = {
83
    1,                          /* use fixed settings */
84
    44100,                      /* fixed frequency */
85
    2,                          /* fixed channels */
86
    AUD_FMT_S16,                /* fixed format */
87
    1,                          /* number of hw voices */
88
    -1                          /* voice size */
89
};
90

  
91
/* http://www.df.lth.se/~john_e/gems/gem002d.html */
92
/* http://www.multi-platforms.com/Tips/PopCount.htm */
93
uint32_t popcount (uint32_t u)
94
{
95
    u = ((u&0x55555555) + ((u>>1)&0x55555555));
96
    u = ((u&0x33333333) + ((u>>2)&0x33333333));
97
    u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
98
    u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
99
    u = ( u&0x0000ffff) + (u>>16);
100
    return u;
101
}
102

  
103
inline uint32_t lsbindex (uint32_t u)
104
{
105
    return popcount ((u&-u)-1);
106
}
107

  
108
int audio_get_conf_int (const char *key, int defval)
109
{
110
    int val = defval;
111
    char *strval;
112

  
113
    strval = getenv (key);
114
    if (strval) {
115
        val = atoi (strval);
116
    }
117

  
118
    return val;
119
}
120

  
121
const char *audio_get_conf_str (const char *key, const char *defval)
122
{
123
    const char *val = getenv (key);
124
    if (!val)
125
        return defval;
126
    else
127
        return val;
128
}
129

  
130
void audio_log (const char *fmt, ...)
131
{
132
    va_list ap;
133
    va_start (ap, fmt);
134
    vfprintf (stderr, fmt, ap);
135
    va_end (ap);
136
}
137

  
138
/*
139
 * Soft Voice
140
 */
141
void pcm_sw_free_resources (SWVoice *sw)
142
{
143
    if (sw->buf) qemu_free (sw->buf);
144
    if (sw->rate) st_rate_stop (sw->rate);
145
    sw->buf = NULL;
146
    sw->rate = NULL;
147
}
148

  
149
int pcm_sw_alloc_resources (SWVoice *sw)
150
{
151
    sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));
152
    if (!sw->buf)
153
        return -1;
154

  
155
    sw->rate = st_rate_start (sw->freq, sw->hw->freq);
156
    if (!sw->rate) {
157
        qemu_free (sw->buf);
158
        sw->buf = NULL;
159
        return -1;
160
    }
161
    return 0;
162
}
163

  
164
void pcm_sw_fini (SWVoice *sw)
165
{
166
    pcm_sw_free_resources (sw);
167
}
168

  
169
int pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
170
                 int nchannels, audfmt_e fmt)
171
{
172
    int bits = 8, sign = 0;
173

  
174
    switch (fmt) {
175
    case AUD_FMT_S8:
176
        sign = 1;
177
    case AUD_FMT_U8:
178
        break;
179

  
180
    case AUD_FMT_S16:
181
        sign = 1;
182
    case AUD_FMT_U16:
183
        bits = 16;
184
        break;
185
    }
186

  
187
    sw->hw = hw;
188
    sw->freq = freq;
189
    sw->fmt = fmt;
190
    sw->nchannels = nchannels;
191
    sw->shift = (nchannels == 2) + (bits == 16);
192
    sw->align = (1 << sw->shift) - 1;
193
    sw->left = 0;
194
    sw->pos = 0;
195
    sw->wpos = 0;
196
    sw->live = 0;
197
    sw->ratio = (sw->hw->freq * ((int64_t) INT_MAX)) / sw->freq;
198
    sw->bytes_per_second = sw->freq << sw->shift;
199
    sw->conv = mixeng_conv[nchannels == 2][sign][bits == 16];
200

  
201
    pcm_sw_free_resources (sw);
202
    return pcm_sw_alloc_resources (sw);
203
}
204

  
205
/* Hard voice */
206
void pcm_hw_free_resources (HWVoice *hw)
207
{
208
    if (hw->mix_buf)
209
        qemu_free (hw->mix_buf);
210
    hw->mix_buf = NULL;
211
}
212

  
213
int pcm_hw_alloc_resources (HWVoice *hw)
214
{
215
    hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));
216
    if (!hw->mix_buf)
217
        return -1;
218
    return 0;
219
}
220

  
221

  
222
void pcm_hw_fini (HWVoice *hw)
223
{
224
    if (hw->active) {
225
        ldebug ("pcm_hw_fini: %d %d %d\n", hw->freq, hw->nchannels, hw->fmt);
226
        pcm_hw_free_resources (hw);
227
        hw->pcm_ops->fini (hw);
228
        memset (hw, 0, audio_state.drv->voice_size);
229
    }
230
}
231

  
232
void pcm_hw_gc (HWVoice *hw)
233
{
234
    if (hw->nb_voices)
235
        return;
236

  
237
    pcm_hw_fini (hw);
238
}
239

  
240
int pcm_hw_get_live (HWVoice *hw)
241
{
242
    int i, alive = 0, live = hw->samples;
243

  
244
    for (i = 0; i < hw->nb_voices; i++) {
245
        if (hw->pvoice[i]->live) {
246
            live = audio_MIN (hw->pvoice[i]->live, live);
247
            alive += 1;
248
        }
249
    }
250

  
251
    if (alive)
252
        return live;
253
    else
254
        return -1;
255
}
256

  
257
int pcm_hw_get_live2 (HWVoice *hw, int *nb_active)
258
{
259
    int i, alive = 0, live = hw->samples;
260

  
261
    *nb_active = 0;
262
    for (i = 0; i < hw->nb_voices; i++) {
263
        if (hw->pvoice[i]->live) {
264
            if (hw->pvoice[i]->live < live) {
265
                *nb_active = hw->pvoice[i]->active != 0;
266
                live = hw->pvoice[i]->live;
267
            }
268
            alive += 1;
269
        }
270
    }
271

  
272
    if (alive)
273
        return live;
274
    else
275
        return -1;
276
}
277

  
278
void pcm_hw_dec_live (HWVoice *hw, int decr)
279
{
280
    int i;
281

  
282
    for (i = 0; i < hw->nb_voices; i++) {
283
        if (hw->pvoice[i]->live) {
284
            hw->pvoice[i]->live -= decr;
285
        }
286
    }
287
}
288

  
289
void pcm_hw_clear (HWVoice *hw, void *buf, int len)
290
{
291
    if (!len)
292
        return;
293

  
294
    switch (hw->fmt) {
295
    case AUD_FMT_S16:
296
    case AUD_FMT_S8:
297
        memset (buf, len << hw->shift, 0x00);
298
        break;
299

  
300
    case AUD_FMT_U8:
301
        memset (buf, len << hw->shift, 0x80);
302
        break;
303

  
304
    case AUD_FMT_U16:
305
        {
306
            unsigned int i;
307
            uint16_t *p = buf;
308
            int shift = hw->nchannels - 1;
309

  
310
            for (i = 0; i < len << shift; i++) {
311
                p[i] = INT16_MAX;
312
            }
313
        }
314
        break;
315
    }
316
}
317

  
318
int pcm_hw_write (SWVoice *sw, void *buf, int size)
319
{
320
    int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
321
    int ret = 0, pos = 0;
322
    if (!sw)
323
        return size;
324

  
325
    hwsamples = sw->hw->samples;
326
    samples = size >> sw->shift;
327

  
328
    if (!sw->live) {
329
        sw->wpos = sw->hw->rpos;
330
    }
331
    wpos = sw->wpos;
332
    live = sw->live;
333
    dead = hwsamples - live;
334
    swlim = (dead * ((int64_t) INT_MAX)) / sw->ratio;
335
    swlim = audio_MIN (swlim, samples);
336

  
337
    ldebug ("size=%d live=%d dead=%d swlim=%d wpos=%d\n",
338
           size, live, dead, swlim, wpos);
339
    if (swlim)
340
        sw->conv (sw->buf, buf, swlim);
341

  
342
    while (swlim) {
343
        dead = hwsamples - live;
344
        left = hwsamples - wpos;
345
        blck = audio_MIN (dead, left);
346
        if (!blck) {
347
            /* dolog ("swlim=%d\n", swlim); */
348
            break;
349
        }
350
        isamp = swlim;
351
        osamp = blck;
352
        st_rate_flow (sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp);
353
        ret += isamp;
354
        swlim -= isamp;
355
        pos += isamp;
356
        live += osamp;
357
        wpos = (wpos + osamp) % hwsamples;
358
    }
359

  
360
    sw->wpos = wpos;
361
    sw->live = live;
362
    return ret << sw->shift;
363
}
364

  
365
int pcm_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
366
{
367
    int sign = 0, bits = 8;
368

  
369
    pcm_hw_fini (hw);
370
    ldebug ("pcm_hw_init: %d %d %d\n", freq, nchannels, fmt);
371
    if (hw->pcm_ops->init (hw, freq, nchannels, fmt)) {
372
        memset (hw, 0, audio_state.drv->voice_size);
373
        return -1;
374
    }
375

  
376
    switch (hw->fmt) {
377
    case AUD_FMT_S8:
378
        sign = 1;
379
    case AUD_FMT_U8:
380
        break;
381

  
382
    case AUD_FMT_S16:
383
        sign = 1;
384
    case AUD_FMT_U16:
385
        bits = 16;
386
        break;
387
    }
388

  
389
    hw->nb_voices = 0;
390
    hw->active = 1;
391
    hw->shift = (hw->nchannels == 2) + (bits == 16);
392
    hw->bytes_per_second = hw->freq << hw->shift;
393
    hw->align = (1 << hw->shift) - 1;
394
    hw->samples = hw->bufsize >> hw->shift;
395
    hw->clip = mixeng_clip[hw->nchannels == 2][sign][bits == 16];
396
    if (pcm_hw_alloc_resources (hw)) {
397
        pcm_hw_fini (hw);
398
        return -1;
399
    }
400
    return 0;
401
}
402

  
403
static int dist (void *hw)
404
{
405
    if (hw) {
406
        return (((uint8_t *) hw - (uint8_t *) hw_voice)
407
                / audio_state.voice_size) + 1;
408
    }
409
    else {
410
        return 0;
411
    }
412
}
413

  
414
#define ADVANCE(hw) hw ? advance (hw, audio_state.voice_size) : hw_voice
415

  
416
HWVoice *pcm_hw_find_any (HWVoice *hw)
417
{
418
    int i = dist (hw);
419
    for (; i < audio_state.nb_hw_voices; i++) {
420
        hw = ADVANCE (hw);
421
        return hw;
422
    }
423
    return NULL;
424
}
425

  
426
HWVoice *pcm_hw_find_any_active (HWVoice *hw)
427
{
428
    int i = dist (hw);
429
    for (; i < audio_state.nb_hw_voices; i++) {
430
        hw = ADVANCE (hw);
431
        if (hw->active)
432
            return hw;
433
    }
434
    return NULL;
435
}
436

  
437
HWVoice *pcm_hw_find_any_active_enabled (HWVoice *hw)
438
{
439
    int i = dist (hw);
440
    for (; i < audio_state.nb_hw_voices; i++) {
441
        hw = ADVANCE (hw);
442
        if (hw->active && hw->enabled)
443
            return hw;
444
    }
445
    return NULL;
446
}
447

  
448
HWVoice *pcm_hw_find_any_passive (HWVoice *hw)
449
{
450
    int i = dist (hw);
451
    for (; i < audio_state.nb_hw_voices; i++) {
452
        hw = ADVANCE (hw);
453
        if (!hw->active)
454
            return hw;
455
    }
456
    return NULL;
457
}
458

  
459
HWVoice *pcm_hw_find_specific (HWVoice *hw, int freq,
460
                               int nchannels, audfmt_e fmt)
461
{
462
    while ((hw = pcm_hw_find_any_active (hw))) {
463
        if (hw->freq == freq &&
464
            hw->nchannels == nchannels &&
465
            hw->fmt == fmt)
466
            return hw;
467
    }
468
    return NULL;
469
}
470

  
471
HWVoice *pcm_hw_add (int freq, int nchannels, audfmt_e fmt)
472
{
473
    HWVoice *hw;
474

  
475
    if (audio_state.fixed_format) {
476
        freq = audio_state.fixed_freq;
477
        nchannels = audio_state.fixed_channels;
478
        fmt = audio_state.fixed_fmt;
479
    }
480

  
481
    hw = pcm_hw_find_specific (NULL, freq, nchannels, fmt);
482

  
483
    if (hw)
484
        return hw;
485

  
486
    hw = pcm_hw_find_any_passive (NULL);
487
    if (hw) {
488
        hw->pcm_ops = audio_state.drv->pcm_ops;
489
        if (!hw->pcm_ops)
490
            return NULL;
491

  
492
        if (pcm_hw_init (hw, freq, nchannels, fmt)) {
493
            pcm_hw_gc (hw);
494
            return NULL;
495
        }
496
        else
497
            return hw;
498
    }
499

  
500
    return pcm_hw_find_any (NULL);
501
}
502

  
503
int pcm_hw_add_sw (HWVoice *hw, SWVoice *sw)
504
{
505
    SWVoice **pvoice = qemu_mallocz ((hw->nb_voices + 1) * sizeof (sw));
506
    if (!pvoice)
507
        return -1;
508

  
509
    memcpy (pvoice, hw->pvoice, hw->nb_voices * sizeof (sw));
510
    qemu_free (hw->pvoice);
511
    hw->pvoice = pvoice;
512
    hw->pvoice[hw->nb_voices++] = sw;
513
    return 0;
514
}
515

  
516
int pcm_hw_del_sw (HWVoice *hw, SWVoice *sw)
517
{
518
    int i, j;
519
    if (hw->nb_voices > 1) {
520
        SWVoice **pvoice = qemu_mallocz ((hw->nb_voices - 1) * sizeof (sw));
521

  
522
        if (!pvoice) {
523
            dolog ("Can not maintain consistent state (not enough memory)\n");
524
            return -1;
525
        }
526

  
527
        for (i = 0, j = 0; i < hw->nb_voices; i++) {
528
            if (j >= hw->nb_voices - 1) {
529
                dolog ("Can not maintain consistent state "
530
                       "(invariant violated)\n");
531
                return -1;
532
            }
533
            if (hw->pvoice[i] != sw)
534
                pvoice[j++] = hw->pvoice[i];
535
        }
536
        qemu_free (hw->pvoice);
537
        hw->pvoice = pvoice;
538
        hw->nb_voices -= 1;
539
    }
540
    else {
541
        qemu_free (hw->pvoice);
542
        hw->pvoice = NULL;
543
        hw->nb_voices = 0;
544
    }
545
    return 0;
546
}
547

  
548
SWVoice *pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt)
549
{
550
    SWVoice *sw;
551
    HWVoice *hw;
552

  
553
    sw = qemu_mallocz (sizeof (*sw));
554
    if (!sw)
555
        goto err1;
556

  
557
    hw = pcm_hw_add (freq, nchannels, fmt);
558
    if (!hw)
559
        goto err2;
560

  
561
    if (pcm_hw_add_sw (hw, sw))
562
        goto err3;
563

  
564
    if (pcm_sw_init (sw, hw, freq, nchannels, fmt))
565
        goto err4;
566

  
567
    return sw;
568

  
569
err4:
570
    pcm_hw_del_sw (hw, sw);
571
err3:
572
    pcm_hw_gc (hw);
573
err2:
574
    qemu_free (sw);
575
err1:
576
    return NULL;
577
}
578

  
579
SWVoice *AUD_open (SWVoice *sw, const char *name,
580
                   int freq, int nchannels, audfmt_e fmt)
581
{
582
    if (!audio_state.drv) {
583
        return NULL;
584
    }
585

  
586
    if (sw && freq == sw->freq && sw->nchannels == nchannels && sw->fmt == fmt) {
587
        return sw;
588
    }
589

  
590
    if (sw) {
591
        ldebug ("Different format %s %d %d %d\n",
592
                name,
593
                sw->freq == freq,
594
                sw->nchannels == nchannels,
595
                sw->fmt == fmt);
596
    }
597

  
598
    if (nchannels != 1 && nchannels != 2) {
599
        dolog ("Bogus channel count %d for voice %s\n", nchannels, name);
600
        return NULL;
601
    }
602

  
603
    if (!audio_state.fixed_format && sw) {
604
        pcm_sw_fini (sw);
605
        pcm_hw_del_sw (sw->hw, sw);
606
        pcm_hw_gc (sw->hw);
607
        if (sw->name) {
608
            qemu_free (sw->name);
609
            sw->name = NULL;
610
        }
611
        qemu_free (sw);
612
        sw = NULL;
613
    }
614

  
615
    if (sw) {
616
        HWVoice *hw = sw->hw;
617
        if (!hw) {
618
            dolog ("Internal logic error voice %s has no hardware store\n",
619
                   name);
620
            return sw;
621
        }
622

  
623
        if (pcm_sw_init (sw, hw, freq, nchannels, fmt)) {
624
            pcm_sw_fini (sw);
625
            pcm_hw_del_sw (hw, sw);
626
            pcm_hw_gc (hw);
627
            if (sw->name) {
628
                qemu_free (sw->name);
629
                sw->name = NULL;
630
            }
631
            qemu_free (sw);
632
            return NULL;
633
        }
634
    }
635
    else {
636
        sw = pcm_create_voice_pair (freq, nchannels, fmt);
637
        if (!sw) {
638
            dolog ("Failed to create voice %s\n", name);
639
            return NULL;
640
        }
641
    }
642

  
643
    if (sw->name) {
644
        qemu_free (sw->name);
645
        sw->name = NULL;
646
    }
647
    sw->name = qemu_strdup (name);
648
    return sw;
649
}
650

  
651
int AUD_write (SWVoice *sw, void *buf, int size)
652
{
653
    int bytes;
654

  
655
    if (!sw->hw->enabled)
656
        dolog ("Writing to disabled voice %s\n", sw->name);
657
    bytes = sw->hw->pcm_ops->write (sw, buf, size);
658
    return bytes;
659
}
660

  
661
void AUD_run (void)
662
{
663
    HWVoice *hw = NULL;
664

  
665
    while ((hw = pcm_hw_find_any_active_enabled (hw))) {
666
        int i;
667
        if (hw->pending_disable && pcm_hw_get_live (hw) <= 0) {
668
            hw->enabled = 0;
669
            hw->pcm_ops->ctl (hw, VOICE_DISABLE);
670
            for (i = 0; i < hw->nb_voices; i++) {
671
                hw->pvoice[i]->live = 0;
672
                /* hw->pvoice[i]->old_ticks = 0; */
673
            }
674
            continue;
675
        }
676

  
677
        hw->pcm_ops->run (hw);
678
        assert (hw->rpos < hw->samples);
679
        for (i = 0; i < hw->nb_voices; i++) {
680
            SWVoice *sw = hw->pvoice[i];
681
            if (!sw->active && !sw->live && sw->old_ticks) {
682
                int64_t delta = qemu_get_clock (vm_clock) - sw->old_ticks;
683
                if (delta > audio_state.ticks_threshold) {
684
                    ldebug ("resetting old_ticks for %s\n", sw->name);
685
                    sw->old_ticks = 0;
686
                }
687
            }
688
        }
689
    }
690
}
691

  
692
int AUD_get_free (SWVoice *sw)
693
{
694
    int free;
695

  
696
    if (!sw)
697
        return 4096;
698

  
699
    free = ((sw->hw->samples - sw->live) << sw->hw->shift) * sw->ratio
700
        / INT_MAX;
701

  
702
    free &= ~sw->hw->align;
703
    if (!free) return 0;
704

  
705
    return free;
706
}
707

  
708
int AUD_get_buffer_size (SWVoice *sw)
709
{
710
    return sw->hw->bufsize;
711
}
712

  
713
void AUD_adjust (SWVoice *sw, int bytes)
714
{
715
    if (!sw)
716
        return;
717
    sw->old_ticks += (ticks_per_sec * (int64_t) bytes) / sw->bytes_per_second;
718
}
719

  
720
void AUD_reset (SWVoice *sw)
721
{
722
    sw->active = 0;
723
    sw->old_ticks = 0;
724
}
725

  
726
int AUD_calc_elapsed (SWVoice *sw)
727
{
728
    int64_t now, delta, bytes;
729
    int dead, swlim;
730

  
731
    if (!sw)
732
        return 0;
733

  
734
    now = qemu_get_clock (vm_clock);
735
    delta = now - sw->old_ticks;
736
    bytes = (delta * sw->bytes_per_second) / ticks_per_sec;
737
    if (delta < 0) {
738
        dolog ("whoops delta(<0)=%lld\n", delta);
739
        return 0;
740
    }
741

  
742
    dead = sw->hw->samples - sw->live;
743
    swlim = ((dead * (int64_t) INT_MAX) / sw->ratio);
744

  
745
    if (bytes > swlim) {
746
        return swlim;
747
    }
748
    else {
749
        return bytes;
750
    }
751
}
752

  
753
void AUD_enable (SWVoice *sw, int on)
754
{
755
    int i;
756
    HWVoice *hw;
757

  
758
    if (!sw)
759
        return;
760

  
761
    hw = sw->hw;
762
    if (on) {
763
        if (!sw->live)
764
            sw->wpos = sw->hw->rpos;
765
        if (!sw->old_ticks) {
766
            sw->old_ticks = qemu_get_clock (vm_clock);
767
        }
768
    }
769

  
770
    if (sw->active != on) {
771
        if (on) {
772
            hw->pending_disable = 0;
773
            if (!hw->enabled) {
774
                hw->enabled = 1;
775
                for (i = 0; i < hw->nb_voices; i++) {
776
                    ldebug ("resetting voice\n");
777
                    sw = hw->pvoice[i];
778
                    sw->old_ticks = qemu_get_clock (vm_clock);
779
                }
780
                hw->pcm_ops->ctl (hw, VOICE_ENABLE);
781
            }
782
        }
783
        else {
784
            if (hw->enabled && !hw->pending_disable) {
785
                int nb_active = 0;
786
                for (i = 0; i < hw->nb_voices; i++) {
787
                    nb_active += hw->pvoice[i]->active != 0;
788
                }
789

  
790
                if (nb_active == 1) {
791
                    hw->pending_disable = 1;
792
                }
793
            }
794
        }
795
        sw->active = on;
796
    }
797
}
798

  
799
static struct audio_output_driver *drvtab[] = {
800
#ifdef USE_OSS_AUDIO
801
    &oss_output_driver,
802
#endif
803
#ifdef USE_FMOD_AUDIO
804
    &fmod_output_driver,
805
#endif
806
#ifdef USE_SDL_AUDIO
807
    &sdl_output_driver,
808
#endif
809
#ifdef USE_WAV_AUDIO
810
    &wav_output_driver,
811
#endif
812
};
813

  
814
static int voice_init (struct audio_output_driver *drv)
815
{
816
    audio_state.opaque = drv->init ();
817
    if (audio_state.opaque) {
818
        if (audio_state.nb_hw_voices > drv->max_voices) {
819
            dolog ("`%s' does not support %d multiple hardware channels\n"
820
                   "Resetting to %d\n",
821
                   drv->name, audio_state.nb_hw_voices, drv->max_voices);
822
            audio_state.nb_hw_voices = drv->max_voices;
823
        }
824
        hw_voice = qemu_mallocz (audio_state.nb_hw_voices * drv->voice_size);
825
        if (hw_voice) {
826
            audio_state.drv = drv;
827
            return 1;
828
        }
829
        else {
830
            dolog ("Not enough memory for %d `%s' voices (each %d bytes)\n",
831
                   audio_state.nb_hw_voices, drv->name, drv->voice_size);
832
            drv->fini (audio_state.opaque);
833
            return 0;
834
        }
835
    }
836
    else {
837
        dolog ("Could not init `%s' audio\n", drv->name);
838
        return 0;
839
    }
840
}
841

  
842
static void audio_vm_stop_handler (void *opaque, int reason)
843
{
844
    HWVoice *hw = NULL;
845

  
846
    while ((hw = pcm_hw_find_any (hw))) {
847
        if (!hw->pcm_ops)
848
            continue;
849

  
850
        hw->pcm_ops->ctl (hw, reason ? VOICE_ENABLE : VOICE_DISABLE);
851
    }
852
}
853

  
854
static void audio_atexit (void)
855
{
856
    HWVoice *hw = NULL;
857

  
858
    while ((hw = pcm_hw_find_any (hw))) {
859
        if (!hw->pcm_ops)
860
            continue;
861

  
862
        hw->pcm_ops->ctl (hw, VOICE_DISABLE);
863
        hw->pcm_ops->fini (hw);
864
    }
865
    audio_state.drv->fini (audio_state.opaque);
866
}
867

  
868
static void audio_save (QEMUFile *f, void *opaque)
869
{
870
}
871

  
872
static int audio_load (QEMUFile *f, void *opaque, int version_id)
873
{
874
    if (version_id != 1)
875
        return -EINVAL;
876

  
877
    return 0;
878
}
879

  
880
void AUD_init (void)
881
{
882
    int i;
883
    int done = 0;
884
    const char *drvname;
885

  
886
    audio_state.fixed_format =
887
        !!audio_get_conf_int (QC_FIXED_FORMAT, audio_state.fixed_format);
888
    audio_state.fixed_freq =
889
        audio_get_conf_int (QC_FIXED_FREQ, audio_state.fixed_freq);
890
    audio_state.nb_hw_voices =
891
        audio_get_conf_int (QC_VOICES, audio_state.nb_hw_voices);
892

  
893
    if (audio_state.nb_hw_voices <= 0) {
894
        dolog ("Bogus number of voices %d, resetting to 1\n",
895
               audio_state.nb_hw_voices);
896
    }
897

  
898
    drvname = audio_get_conf_str (QC_AUDIO_DRV, NULL);
899
    if (drvname) {
900
        int found = 0;
901
        for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
902
            if (!strcmp (drvname, drvtab[i]->name)) {
903
                done = voice_init (drvtab[i]);
904
                found = 1;
905
                break;
906
            }
907
        }
908
        if (!found) {
909
            dolog ("Unknown audio driver `%s'\n", drvname);
910
        }
911
    }
912

  
913
    qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
914
    atexit (audio_atexit);
915

  
916
    if (!done) {
917
        for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
918
            if (drvtab[i]->can_be_default)
919
                done = voice_init (drvtab[i]);
920
        }
921
    }
922

  
923
    audio_state.ticks_threshold = ticks_per_sec / 50;
924
    audio_state.freq_threshold = 100;
925

  
926
    register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);
927
    if (!done) {
928
        dolog ("Can not initialize audio subsystem\n");
929
        return;
930
    }
931

  
932
    for (i = 0; hw_ctors[i]; i++) {
933
        hw_ctors[i] ();
934
    }
935
}
b/audio/audio.h
1
/*
2
 * QEMU Audio subsystem header
3
 * 
4
 * Copyright (c) 2003-2004 Vassili Karpov (malc)
5
 * 
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
#ifndef QEMU_AUDIO_H
25
#define QEMU_AUDIO_H
26

  
27
#include "mixeng.h"
28

  
29
#define dolog(...) fprintf (stderr, AUDIO_CAP ": " __VA_ARGS__)
30
#ifdef DEBUG
31
#define ldebug(...) dolog (__VA_ARGS__)
32
#else
33
#define ldebug(...)
34
#endif
35

  
36
typedef enum {
37
  AUD_FMT_U8,
38
  AUD_FMT_S8,
39
  AUD_FMT_U16,
40
  AUD_FMT_S16
41
} audfmt_e;
42

  
43
typedef struct HWVoice HWVoice;
44
struct audio_output_driver;
45

  
46
typedef struct AudioState {
47
    int fixed_format;
48
    int fixed_freq;
49
    int fixed_channels;
50
    int fixed_fmt;
51
    int nb_hw_voices;
52
    int voice_size;
53
    int64_t ticks_threshold;
54
    int freq_threshold;
55
    void *opaque;
56
    struct audio_output_driver *drv;
57
} AudioState;
58

  
59
extern AudioState audio_state;
60

  
61
typedef struct SWVoice {
62
    int freq;
63
    audfmt_e fmt;
64
    int nchannels;
65

  
66
    int shift;
67
    int align;
68

  
69
    t_sample *conv;
70

  
71
    int left;
72
    int pos;
73
    int bytes_per_second;
74
    int64_t ratio;
75
    st_sample_t *buf;
76
    void *rate;
77

  
78
    int wpos;
79
    int live;
80
    int active;
81
    int64_t old_ticks;
82
    HWVoice *hw;
83
    char *name;
84
} SWVoice;
85

  
86
#define VOICE_ENABLE 1
87
#define VOICE_DISABLE 2
88

  
89
struct pcm_ops {
90
    int  (*init)  (HWVoice *hw, int freq, int nchannels, audfmt_e fmt);
91
    void (*fini)  (HWVoice *hw);
92
    void (*run)   (HWVoice *hw);
93
    int  (*write) (SWVoice *sw, void *buf, int size);
94
    int  (*ctl)   (HWVoice *hw, int cmd, ...);
95
};
96

  
97
struct audio_output_driver {
98
    const char *name;
99
    void *(*init) (void);
100
    void (*fini) (void *);
101
    struct pcm_ops *pcm_ops;
102
    int can_be_default;
103
    int max_voices;
104
    int voice_size;
105
};
106

  
107
struct HWVoice {
108
    int active;
109
    int enabled;
110
    int pending_disable;
111
    int valid;
112
    int freq;
113

  
114
    f_sample *clip;
115
    audfmt_e fmt;
116
    int nchannels;
117

  
118
    int align;
119
    int shift;
120

  
121
    int rpos;
122
    int bufsize;
123

  
124
    int bytes_per_second;
125
    st_sample_t *mix_buf;
126

  
127
    int samples;
128
    int64_t old_ticks;
129
    int nb_voices;
130
    struct SWVoice **pvoice;
131
    struct pcm_ops *pcm_ops;
132
};
133

  
134
void      audio_log (const char *fmt, ...);
135
void      pcm_sw_free_resources (SWVoice *sw);
136
int       pcm_sw_alloc_resources (SWVoice *sw);
137
void      pcm_sw_fini (SWVoice *sw);
138
int       pcm_sw_init (SWVoice *sw, HWVoice *hw, int freq,
139
                       int nchannels, audfmt_e fmt);
140

  
141
void      pcm_hw_clear (HWVoice *hw, void *buf, int len);
142
HWVoice * pcm_hw_find_any (HWVoice *hw);
143
HWVoice * pcm_hw_find_any_active (HWVoice *hw);
144
HWVoice * pcm_hw_find_any_passive (HWVoice *hw);
145
HWVoice * pcm_hw_find_specific (HWVoice *hw, int freq,
146
                                int nchannels, audfmt_e fmt);
147
HWVoice * pcm_hw_add (int freq, int nchannels, audfmt_e fmt);
148
int       pcm_hw_add_sw (HWVoice *hw, SWVoice *sw);
149
int       pcm_hw_del_sw (HWVoice *hw, SWVoice *sw);
150
SWVoice * pcm_create_voice_pair (int freq, int nchannels, audfmt_e fmt);
151

  
152
void      pcm_hw_free_resources (HWVoice *hw);
153
int       pcm_hw_alloc_resources (HWVoice *hw);
154
void      pcm_hw_fini (HWVoice *hw);
155
void      pcm_hw_gc (HWVoice *hw);
156
int       pcm_hw_get_live (HWVoice *hw);
157
int       pcm_hw_get_live2 (HWVoice *hw, int *nb_active);
158
void      pcm_hw_dec_live (HWVoice *hw, int decr);
159
int       pcm_hw_write (SWVoice *sw, void *buf, int len);
160

  
161
int         audio_get_conf_int (const char *key, int defval);
162
const char *audio_get_conf_str (const char *key, const char *defval);
163

  
164
/* Public API */
165
SWVoice * AUD_open (SWVoice *sw, const char *name, int freq,
166
                    int nchannels, audfmt_e fmt);
167
int    AUD_write (SWVoice *sw, void *pcm_buf, int size);
168
void   AUD_adjust (SWVoice *sw, int leftover);
169
void   AUD_reset (SWVoice *sw);
170
int    AUD_get_free (SWVoice *sw);
171
int    AUD_get_buffer_size (SWVoice *sw);
172
void   AUD_run (void);
173
void   AUD_enable (SWVoice *sw, int on);
174
int    AUD_calc_elapsed (SWVoice *sw);
175

  
176
static inline void *advance (void *p, int incr)
177
{
178
    uint8_t *d = p;
179
    return (d + incr);
180
}
181

  
182
uint32_t popcount (uint32_t u);
183
inline uint32_t lsbindex (uint32_t u);
184

  
185
#define audio_MIN(a, b) ((a)>(b)?(b):(a))
186
#define audio_MAX(a, b) ((a)<(b)?(b):(a))
187

  
188
#endif  /* audio.h */
b/audio/fmodaudio.c
1
/*
2
 * QEMU FMOD audio output driver
3
 * 
4
 * Copyright (c) 2004 Vassili Karpov (malc)
5
 * 
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>
26
#include "vl.h"
27

  
28
#define AUDIO_CAP "fmod"
29
#include "audio/audio.h"
30
#include "audio/fmodaudio.h"
31

  
32
#define QC_FMOD_DRV "QEMU_FMOD_DRV"
33
#define QC_FMOD_FREQ "QEMU_FMOD_FREQ"
34
#define QC_FMOD_SAMPLES "QEMU_FMOD_SAMPLES"
35
#define QC_FMOD_CHANNELS "QEMU_FMOD_CHANNELS"
36
#define QC_FMOD_BUFSIZE "QEMU_FMOD_BUFSIZE"
37
#define QC_FMOD_THRESHOLD "QEMU_FMOD_THRESHOLD"
38

  
39
static struct {
40
    int nb_samples;
41
    int freq;
42
    int nb_channels;
43
    int bufsize;
44
    int threshold;
45
} conf = {
46
    2048,
47
    44100,
48
    1,
49
    0,
50
    128
51
};
52

  
53
#define errstr() FMOD_ErrorString (FSOUND_GetError ())
54

  
55
static int fmod_hw_write (SWVoice *sw, void *buf, int len)
56
{
57
    return pcm_hw_write (sw, buf, len);
58
}
59

  
60
static void fmod_clear_sample (FMODVoice *fmd)
61
{
62
    HWVoice *hw = &fmd->hw;
63
    int status;
64
    void *p1 = 0, *p2 = 0;
65
    unsigned int len1 = 0, len2 = 0;
66

  
67
    status = FSOUND_Sample_Lock (
68
        fmd->fmod_sample,
69
        0,
70
        hw->samples << hw->shift,
71
        &p1,
72
        &p2,
73
        &len1,
74
        &len2
75
        );
76

  
77
    if (!status) {
78
        dolog ("Failed to lock sample\nReason: %s\n", errstr ());
79
        return;
80
    }
81

  
82
    if ((len1 & hw->align) || (len2 & hw->align)) {
83
        dolog ("Locking sample returned unaligned length %d, %d\n",
84
               len1, len2);
85
        goto fail;
86
    }
87

  
88
    if (len1 + len2 != hw->samples << hw->shift) {
89
        dolog ("Locking sample returned incomplete length %d, %d\n",
90
               len1 + len2, hw->samples << hw->shift);
91
        goto fail;
92
    }
93
    pcm_hw_clear (hw, p1, hw->samples);
94

  
95
 fail:
96
    status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
97
    if (!status) {
98
        dolog ("Failed to unlock sample\nReason: %s\n", errstr ());
99
    }
100
}
101

  
102
static int fmod_write_sample (HWVoice *hw, uint8_t *dst, st_sample_t *src,
103
                              int src_size, int src_pos, int dst_len)
104
{
105
    int src_len1 = dst_len, src_len2 = 0, pos = src_pos + dst_len;
106
    st_sample_t *src1 = src + src_pos, *src2 = 0;
107

  
108
    if (src_pos + dst_len > src_size) {
109
        src_len1 = src_size - src_pos;
110
        src2 = src;
111
        src_len2 = dst_len - src_len1;
112
        pos = src_len2;
113
    }
114

  
115
    if (src_len1) {
116
        hw->clip (dst, src1, src_len1);
117
        memset (src1, 0, src_len1 * sizeof (st_sample_t));
118
        advance (dst, src_len1);
119
    }
120

  
121
    if (src_len2) {
122
        hw->clip (dst, src2, src_len2);
123
        memset (src2, 0, src_len2 * sizeof (st_sample_t));
124
    }
125
    return pos;
126
}
127

  
128
static int fmod_unlock_sample (FMODVoice *fmd, void *p1, void *p2,
129
                               unsigned int blen1, unsigned int blen2)
130
{
131
    int status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, blen1, blen2);
132
    if (!status) {
133
        dolog ("Failed to unlock sample\nReason: %s\n", errstr ());
134
        return -1;
135
    }
136
    return 0;
137
}
138

  
139
static int fmod_lock_sample (FMODVoice *fmd, int pos, int len,
140
                             void **p1, void **p2,
141
                             unsigned int *blen1, unsigned int *blen2)
142
{
143
    HWVoice *hw = &fmd->hw;
144
    int status;
145

  
146
    status = FSOUND_Sample_Lock (
147
        fmd->fmod_sample,
148
        pos << hw->shift,
149
        len << hw->shift,
150
        p1,
151
        p2,
152
        blen1,
153
        blen2
154
        );
155

  
156
    if (!status) {
157
        dolog ("Failed to lock sample\nReason: %s\n", errstr ());
158
        return -1;
159
    }
160

  
161
    if ((*blen1 & hw->align) || (*blen2 & hw->align)) {
162
        dolog ("Locking sample returned unaligned length %d, %d\n",
163
               *blen1, *blen2);
164
        fmod_unlock_sample (fmd, *p1, *p2, *blen1, *blen2);
165
        return -1;
166
    }
167
    return 0;
168
}
169

  
170
static void fmod_hw_run (HWVoice *hw)
171
{
172
    FMODVoice *fmd = (FMODVoice *) hw;
173
    int rpos, live, decr;
174
    void *p1 = 0, *p2 = 0;
175
    unsigned int blen1 = 0, blen2 = 0;
176
    unsigned int len1 = 0, len2 = 0;
177
    int nb_active;
178

  
179
    live = pcm_hw_get_live2 (hw, &nb_active);
180
    if (live <= 0) {
181
        return;
182
    }
183

  
184
    if (!hw->pending_disable
185
        && nb_active
186
        && conf.threshold
187
        && live <= conf.threshold) {
188
        ldebug ("live=%d nb_active=%d\n", live, nb_active);
189
        return;
190
    }
191

  
192
    decr = live;
193

  
194
#if 1
195
    if (fmd->channel >= 0) {
196
        int pos2 = (fmd->old_pos + decr) % hw->samples;
197
        int pos = FSOUND_GetCurrentPosition (fmd->channel);
198

  
199
        if (fmd->old_pos < pos && pos2 >= pos) {
200
            decr = pos - fmd->old_pos - (pos2 == pos) - 1;
201
        }
202
        else if (fmd->old_pos > pos && pos2 >= pos && pos2 < fmd->old_pos) {
203
            decr = (hw->samples - fmd->old_pos) + pos - (pos2 == pos) - 1;
204
        }
205
/*         ldebug ("pos=%d pos2=%d old=%d live=%d decr=%d\n", */
206
/*                 pos, pos2, fmd->old_pos, live, decr); */
207
    }
208
#endif
209

  
210
    if (decr <= 0) {
211
        return;
212
    }
213

  
214
    if (fmod_lock_sample (fmd, fmd->old_pos, decr, &p1, &p2, &blen1, &blen2)) {
215
        return;
216
    }
217

  
218
    len1 = blen1 >> hw->shift;
219
    len2 = blen2 >> hw->shift;
220
    ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
221
    decr = len1 + len2;
222
    rpos = hw->rpos;
223

  
224
    if (len1) {
225
        rpos = fmod_write_sample (hw, p1, hw->mix_buf, hw->samples, rpos, len1);
226
    }
227

  
228
    if (len2) {
229
        rpos = fmod_write_sample (hw, p2, hw->mix_buf, hw->samples, rpos, len2);
230
    }
231

  
232
    fmod_unlock_sample (fmd, p1, p2, blen1, blen2);
233

  
234
    pcm_hw_dec_live (hw, decr);
235
    hw->rpos = rpos % hw->samples;
236
    fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
237
}
238

  
239
static int AUD_to_fmodfmt (audfmt_e fmt, int stereo)
240
{
241
    int mode = FSOUND_LOOP_NORMAL;
242

  
243
    switch (fmt) {
244
    case AUD_FMT_S8:
245
        mode |= FSOUND_SIGNED | FSOUND_8BITS;
246
        break;
247

  
248
    case AUD_FMT_U8:
249
        mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
250
        break;
251

  
252
    case AUD_FMT_S16:
253
        mode |= FSOUND_SIGNED | FSOUND_16BITS;
254
        break;
255

  
256
    case AUD_FMT_U16:
257
        mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
258
        break;
259

  
260
    default:
261
        dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
262
        exit (EXIT_FAILURE);
263
    }
264
    mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
265
    return mode;
266
}
267

  
268
static void fmod_hw_fini (HWVoice *hw)
269
{
270
    FMODVoice *fmd = (FMODVoice *) hw;
271

  
272
    if (fmd->fmod_sample) {
273
        FSOUND_Sample_Free (fmd->fmod_sample);
274
        fmd->fmod_sample = 0;
275

  
276
        if (fmd->channel >= 0) {
277
            FSOUND_StopSound (fmd->channel);
278
        }
279
    }
280
}
281

  
282
static int fmod_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff